diff options
author | Julien Valroff <julien@kirya.net> | 2009-07-26 12:15:05 +0000 |
---|---|---|
committer | Julien Valroff <julien@kirya.net> | 2009-07-26 12:15:05 +0000 |
commit | f794c204aa3af1798684522cfcf2024e90752310 (patch) | |
tree | d718a9124857a5cbcd62268d44c092471d2e7288 |
[svn-inject] Installing original source of rapid-photo-downloader
44 files changed, 22925 insertions, 0 deletions
diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..d1a0900 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,14 @@ +Metadata-Version: 1.0 +Name: rapid-photo-downloader +Version: 0.0.10 +Summary: Rapid Photo Downloader for Linux +Home-page: http://www.damonlynch.net/rapid +Author: Damon Lynch +Author-email: damonlynch@gmail.com +License: GPL +Description: Rapid Photo Downloader is written by a photographer for + professional and amateur photographers. It can download photos + from multiple cameras, memory cards and Portable Storage Devices + simultaneously. It provides many options for subfolder creation, + image renaming and backup. +Platform: linux @@ -0,0 +1,50 @@ +Rapid Photo Downloader is written by a photographer for professional and amateur +photographers. Released under the GNU GPL license, it is designed for use on the +Linux Desktop. It can download photos from multiple cameras, memory cards, and +Portable Storage Devices simultaneously. It provides many options for subfolder +creation, image renaming and backup. + +It can download images directly from only from those cameras supported by +libgphoto2, and only on recent Linux distributions (those that contain gvfs). +This support is experimental. Some cameras do not work. If you cannot browse the +camera's contents in a file manager (e.g. Nautilus), the camera download will +not work until the gvfs support is improved. + +If you can put your camera into PTP mode, you may find it works a lot better. + +Cameras that do not work when not in PTP mode as at May 2009 include the +Canon 20D and 300D. + +For more information see http://damonlynch.net/rapid + +Please report any bug or unexepcted behaviour here: + +https://launchpad.net/rapid/+filebug + +Furthermore, please feel welcome to contribute anything to help this program +reach more people: translations, feature suggestions, code, artwork, and +documentation can always be improved! + +Installation +============ + +See the INSTALL file in the directory rapid. + +Documentation +============= + +See http://damonlynch.net/rapid/documentation + +Running the program +=================== + +Start the program from its menu entry. If you want additional output from the +command line, from a terminal run: + +rapid-photo-downloader + +Known Bugs +========== + +See https://bugs.launchpad.net/rapid/+bugs + diff --git a/data/icons/16x16/apps/rapid-photo-downloader.png b/data/icons/16x16/apps/rapid-photo-downloader.png Binary files differnew file mode 100644 index 0000000..97c7d7c --- /dev/null +++ b/data/icons/16x16/apps/rapid-photo-downloader.png diff --git a/data/icons/22x22/apps/rapid-photo-downloader.png b/data/icons/22x22/apps/rapid-photo-downloader.png Binary files differnew file mode 100644 index 0000000..e04e432 --- /dev/null +++ b/data/icons/22x22/apps/rapid-photo-downloader.png diff --git a/data/icons/24x24/apps/rapid-photo-downloader.png b/data/icons/24x24/apps/rapid-photo-downloader.png Binary files differnew file mode 100644 index 0000000..e6ca472 --- /dev/null +++ b/data/icons/24x24/apps/rapid-photo-downloader.png diff --git a/data/icons/48x48/apps/rapid-photo-downloader.png b/data/icons/48x48/apps/rapid-photo-downloader.png Binary files differnew file mode 100644 index 0000000..52be8ab --- /dev/null +++ b/data/icons/48x48/apps/rapid-photo-downloader.png diff --git a/data/icons/rapid-photo-downloader.xpm b/data/icons/rapid-photo-downloader.xpm new file mode 100644 index 0000000..aad262c --- /dev/null +++ b/data/icons/rapid-photo-downloader.xpm @@ -0,0 +1,223 @@ +/* XPM */ +static char *rapid_photo_downloader[] = { +/* columns rows colors chars-per-pixel */ +"32 32 185 2", +" c #6B2F54", +". c #6F7C47", +"X c #67764F", +"o c #747E43", +"O c #667550", +"+ c #61745B", +"@ c #5C4975", +"# c #405F76", +"$ c #5C517D", +"% c #436173", +"& c #426179", +"* c #BB0D0D", +"= c #BB120C", +"- c #B30E18", +"; c #BF1411", +": c #B3141F", +"> c #B23B01", +", c #A81D25", +"< c #B51621", +"1 c #B61F25", +"2 c #B51F28", +"3 c #CC0202", +"4 c #C90508", +"5 c #D40101", +"6 c #D60C0C", +"7 c #C81818", +"8 c #D41414", +"9 c #D81616", +"0 c #D41A1B", +"q c #D91F1F", +"w c #C6212A", +"e c #CD292F", +"r c #DA2424", +"t c #D92E2F", +"y c #CD2C33", +"u c #CF3036", +"i c #D93032", +"p c #D03439", +"a c #D1383E", +"s c #B14300", +"d c #B24C00", +"f c #B35A00", +"g c #BF5A00", +"h c #B46200", +"j c #B36A00", +"k c #B57200", +"l c #B57C00", +"z c #C06500", +"x c #CC6100", +"c c #C16B00", +"v c #CE6E00", +"b c #D96900", +"n c #C17000", +"m c #CE7400", +"M c #C27C00", +"N c #CF7A00", +"B c #DB7600", +"V c #DC7D00", +"C c #B53D4B", +"Z c #D23C42", +"A c #DC3F40", +"S c #D34247", +"D c #D44448", +"F c #D74B4C", +"G c #D94C4F", +"H c #D54D50", +"J c #DB4F51", +"K c #D65052", +"L c #79813E", +"P c #78854C", +"I c #708056", +"U c #7C8C5C", +"Y c #9D951C", +"T c #B58100", +"R c #AA9D10", +"E c #A29918", +"W c #B4A306", +"Q c #B0A00B", +"! c #B3A716", +"~ c #B7AB11", +"^ c #878D3E", +"/ c #8C903A", +"( c #969A3C", +") c #A1A53F", +"_ c #C38300", +"` c #C48C00", +"' c #D18600", +"] c #DE8300", +"[ c #D28C00", +"{ c #C59400", +"} c #D29200", +"| c #D39B00", +" . c #E09300", +".. c #E19D00", +"X. c #C6A200", +"o. c #C7A800", +"O. c #D5A400", +"+. c #C6B304", +"@. c #CBB600", +"#. c #C2B008", +"$. c #D7B400", +"%. c #D2BE09", +"&. c #C1B517", +"*. c #C7B812", +"=. c #E3A400", +"-. c #E4AA00", +";. c #E5B100", +":. c #E7BE00", +">. c #E6883A", +",. c #E6923A", +"<. c #E8973B", +"1. c #E89C3C", +"2. c #E9A53C", +"3. c #EAAD3C", +"4. c #ECB33C", +"5. c #ECBA3B", +"6. c #D7C304", +"7. c #DCC500", +"8. c #D6C613", +"9. c #D1C318", +"0. c #E8C500", +"q. c #E2CE09", +"w. c #E7D104", +"e. c #EDD400", +"r. c #EEC539", +"t. c #EFCB39", +"y. c #828A43", +"u. c #818E4F", +"i. c #8B9446", +"p. c #909741", +"a. c #959E49", +"s. c #8A9753", +"d. c #9CA244", +"f. c #9FAA7E", +"g. c #BDBD65", +"h. c #B9BB68", +"j. c #C6C35D", +"k. c #C9C359", +"l. c #C3C160", +"z. c #254C83", +"x. c #284F86", +"c. c #2E5687", +"v. c #2D548A", +"b. c #2D588F", +"n. c #315786", +"m. c #325884", +"M. c #30578E", +"N. c #2E5A94", +"B. c #335D94", +"V. c #385F94", +"C. c #305E9A", +"Z. c #356097", +"A. c #3C6496", +"S. c #32619D", +"D. c #39649C", +"F. c #3D689F", +"G. c #3364A2", +"H. c #3B67A0", +"J. c #3C6AA5", +"K. c #3D6CA8", +"L. c #4D5584", +"P. c #595885", +"I. c #615781", +"U. c #625882", +"Y. c #426DA4", +"T. c #416EA8", +"R. c #4770A7", +"E. c #4470A8", +"W. c #4B75AA", +"Q. c #5174A6", +"!. c #5476A8", +"~. c #517AAE", +"^. c #567CB0", +"/. c #657FAC", +"(. c #5E82AF", +"). c #5780B4", +"_. c #5980B2", +"`. c #6386B3", +"'. c #6889B4", +"]. c #8C9A8A", +"[. c #93A085", +"{. c #98A783", +"}. c #9CA980", +"|. c #91A288", +" X c None", +/* pixels */ +" X X X X X X X X X X X X X Xw w w w w w w w w w w w w X X X X X", +" X X X X X X X X X X X X XJ 3.3.4.2.5.1.5.<.r.,.t.>.a S X X X X", +" X X X X X X X X X X X X XF .. .=. .-.] ;.V :.B 0.b 6 q F X X X", +" X X X X X X X X X X X X XH } [ | ' | N O.m $.v $.x 6 5 9 D X X", +" X X X X X X X X X X X X XH _ _ ` M { c { c { c o.g 8 5 6 D X X", +" X X X X X X X X X X X X XH h f h f j d k d l s T > 8 5 5 D X X", +" X X X X X X X X X X X X XJ ; * = * = * = * = * = 7 6 5 r Z X X", +" X X X X X X X X X X X X XC < 2 < 6 6 6 6 6 6 6 6 5 5 5 i e X X", +" X X X(.h.f.g.}.l.{.j.|.k.[.k.].`.@ 3 5 5 5 5 5 5 5 5 5 t y X X", +" X X X`.9.) 8.d.q.a.w.s.e.s.e.u.J._.P.- 3 3 3 3 3 3 3 3 6 Z X X", +" X X X`.&.( *.p.6.i.6.u.7.u.7.U J.G.).P.6 5 5 6 6 5 6 3 5 Z X X", +" X X X`.! / ~ ^ #.y.+.P @.P @.I K.G.T.U.5 5 5 5 5 5 6 3 5 Z X X", +" X X X'.Y L E o R . Q X W O W + K.G.Y.I.5 5 5 5 5 5 5 3 5 a X X", +" X X X'.& m.& n.& v.& c.% v.% A.K.C.W.I.5 5 5 5 5 5 5 3 6 a X X", +" X X X_.T.E.E.E.E.E.E.E.E.E.E.K.G.S.!. 5 5 5 5 5 5 5 3 5 p X X", +" X X X^.G.G.G.G.G.G.G.G.G.G.S.S.C.G.!. 5 5 5 5 5 5 5 3 5 p X X", +" X X X^.G.G.C.G.S.S.S.C.C.C.C.C.C.C.W.$ 5 5 5 5 5 5 5 3 5 u X X", +" X X X^.G.J.J.K.K.K.J.J.J.H.H.J.H.C.H.$ 5 5 5 5 5 5 5 3 5 u X X", +" X X X^.G.G.G.G.G.G.G.S.S.S.C.S.D.N.F.$ 5 5 5 5 5 5 5 5 5 y X X", +" X X X~.G.J.G.G.G.G.G.S.S.S.S.C.C.N.D.$ 5 5 5 5 5 5 5 5 5 y X X", +" X X XW.G.G.G.G.G.G.S.S.S.C.C.C.S.N.D.$ 5 5 5 5 5 5 5 5 5 e X X", +" X X XW.C.G.G.G.S.S.S.C.C.C.C.C.B.N.Z.$ 6 6 6 6 6 6 9 0 6 y X X", +" X X XW.C.G.G.S.G.C.S.C.C.N.C.N.N.N.V.L.2 2 2 2 1 1 1 , 1 2 X X", +" X X XW.C.G.C.G.C.C.C.C.C.C.C.C.N.b.B.V. X X X X X X X X X X X X", +" X X XR.S.C.S.S.C.C.C.C.C.N.N.N.N.b.V.V. X X X X X X X X X X X X", +" X X XY.C.S.S.C.C.C.C.N.C.N.N.N.N.b.B.B. X X X X X X X X X X X X", +" X X XT.C.S.C.C.C.C.C.C.N.N.N.N.b.b.B.M. X X X X X X X X X X X X", +" X X XY.C.C.C.C.C.N.N.N.N.N.N.N.N.b.B.B. X X X X X X X X X X X X", +" X X XY.Y.F.S.Z.Z.Z.Z.V.V.B.B.B.V.V.V.M. X X X X X X X X X X X X", +" X X XM.x.v.M.v.M.v.b.v.v.v.v.v.x.z.v.z. X X X X X X X X X X X X", +" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X", +" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X" +}; diff --git a/data/rapid-photo-downloader.desktop b/data/rapid-photo-downloader.desktop new file mode 100644 index 0000000..7d23906 --- /dev/null +++ b/data/rapid-photo-downloader.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Version=1.0 +Name=Rapid Photo Downloader +GenericName=Rapid Photo Downloader +Comment=Download photos from cameras, memory cards and Portable Storage Devices +Exec=rapid-photo-downloader +Icon=rapid-photo-downloader +MimeType=x-content/image-dcf; +Terminal=false +Type=Application +Categories=Graphics;Photography; diff --git a/doc/rapid-photo-downloader.pod b/doc/rapid-photo-downloader.pod new file mode 100644 index 0000000..8720bf5 --- /dev/null +++ b/doc/rapid-photo-downloader.pod @@ -0,0 +1,76 @@ +=head1 NAME + +rapid-photo-downloader - imports images from cameras, memory cards and other devices + +=head1 SYNOPSIS + +B<rapid-photo-downloader> [options] + +Options: + --version + -h, --help + -v, --verbose + -q, --quiet + -e, --extensions + +=head1 DESCRIPTION + +B<Rapid Photo Downloader> downloads photos from cameras, memory cards and Portable +Storage Devices, providing a variety of options for subfolder creation, +image renaming and backup. It can download images from more than one device in parallel. + + +=head1 OPTIONS + +=item B<--version> + +Displays information about the currently installed version and exits. + +=item B<-h, --help> + +Show help message and exit. + +=item B<-v, --verbose> + +Displays program information on the command line as the program runs. + +=item B<-q, --quiet> + +Only display output errors and warnings to the command line as the program runs. + +=item B<-e, --extensions> + +Displays image file extensions the program recognizes and exits. + +=head1 ENVIRONMENT VARIABLES + +=item B<LOCALEDIR> + +If set, overrides the system-wide directory in which translation data will be searched for. + +=head1 BUGS + +* Support for downloading directly from cameras is experimental. Not all cameras are supported. + +* Closing log window with window manager 'x' instead of 'close' button is not yet supported. + +Please report bugs at https://bugs.launchpad.net/rapid + +=head1 AUTHORS + +B<Rapid Photo Downloader> was written by Damon Lynch <damonlynch@gmail.com>. + +This manual page was written by Damon Lynch. + +=head1 COPYRIGHT + +This program is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + +=cut + diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..2c50971 --- /dev/null +++ b/po/de.po @@ -0,0 +1,1409 @@ +# German translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: 2009-05-30 08:00+0000\n" +"Last-Translator: groovy <Unknown>\n" +"Language-Team: German <de@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-05-30 09:36+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "Rapid Photo Downloader" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "Anzahl der ungültigen Downloads von heute.\n" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "Wert wird auf Null zurückgesetzt.\n" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "Der Vorgabewert für 'Start des Tages' ist ungültig.\n" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "Die Zeit wird auf Mitternacht zurückgesetzt.\n" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "Fehler in den Einstellungen zum Umbenennen der Dateien" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "Diese Einstellungen enthalten einen Fehler:\n" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "Die Einstellungen werden auf die Standardwerte zurückgesetzt." + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "Fehler in den Download-Unterordner Einstellungen" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "Wählen Sie einen Ordner für den Download der Bilder" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "Wählen Sie einen Bilder Ordner" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "" +"Wählen Sie einen Ordner zur Speicherung der Sicherungskopien der Bilder" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Warnung:</b> Die vorhandenen Metadaten der Bilder sind nicht " +"vollständig, der neue Name kann nicht erstellt werden. Bitte wählen Sie " +"andere Einstellungen für die Umbenennung der Bilder</i>" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Warnung:</b> Die vorhandenen Metadaten der Bilder sind nicht " +"vollständig, der gewünschte Ordner kann nicht erstellt werden. Bitte wählen " +"Sie andere Einstellungen für die Erstellung der Ordner</i>" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Beispiel: %s</i>" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "" +"Es wurden einige unnötige Werte in den Einstellungen für Unterordner " +"entfernt." + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" +"Die gewählten Einstellungen für Unterordner sind ungültig und können nicht " +"benutzt werden.\n" +"Sie werden auf Standardwerte zurückgesetzt." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "ExternesLaufwerk1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "ExternesLaufwerk2" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "Überprüfe Laufwerke ..." + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "Fehler in den Programmeinstellungen." + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" +"\n" +"Bitte überprüfen Sie die Einstellungen, starten Sie das Programm neu und " +"versuchen es erneut." + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "Der Download kann nicht weitergeführt werden" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "0 von %s Bildern kopiert" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" +"Überprüfung der Laufwerke abgeschlossen: %(number)s Bilder auf %(device)s " +"gefunden" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "" +"Überprüfung der Laufwerke abgeschlossen: Keine Bilder gefunden auf %s" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "Der Dateiname konnte nicht erzeugt werden" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" +"Quelle: %(source)s\n" +"Problem: %(problem)s" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Der Dateiname konnte nicht erzeugt werden. Bitte überprüfen Sie die " +"Metadaten der Bilddatei." + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" +"Quelle: %(source)s\n" +"Ziel: %(destination)s\n" +"Problem: %(problem)s" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "Das Bild konnte nicht geöffnet werden" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "Quelle: %s" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "Das Bild enthält keine Metadaten" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" +"Die Metadaten sind Voraussetzung für die Erstellung der Unterordner / " +"Dateinamen\n" +"Quelle: %s" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Der Unterordner konnte nicht erzeugt werden. Bitte überprüfen Sie die " +"Metadaten der Bilddatei." + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" +"Unterordner: %(subfolder)s\n" +"Bild: %(image)s\n" +"Problem: %(problem)s" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Quelle: %(source)s\n" +"Ziel: %(destination)s" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "Die eindeutige Bezeichnung '%s' wurde hinzugefügt" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" +"Ein neuer Tag hat begonnen - die Anzahl der 'Downloads Heute' wird " +"zurückgesetzt" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "Fehler beim Kopieren" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" +"Quelle: %(source)s\n" +"Ziel: %(destination)s\n" +"Fehler: %(errorno)s %(strerror)s" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "Die Datei wurde nicht kopiert." + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "Die Sicherungskopie besteht bereits" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "Fehler beim Erstellen der Sicherungskopie" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Das Zielverzeichnis konnte nicht erstellt werden\n" +"%(directory)s\n" +"Fehler: %(errno)s %(strerror)s" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Quelle: %(source)s\n" +"Ziel: %(destination)s\n" +"Fehler: %(errno)s %(strerror)s" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "Das Laufwerk kann nun entfernt werden" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "%s Bilder heruntergeladen" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "%s Bilder übersprungen" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "Warnungen" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "Fehler" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "Das Laufwerk für die Sicherungskopien fehlt" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "Das Laufwerk für die Sicherungskopien konnte nicht gefunden werden." + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "Das Laufwerk enthält keine Bilddateien." + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "Der Download von %s hat begonnen" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "Bild übersprungen" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "Bilddatei überschrieben" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "Bilddatei existiert bereits" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "Die Datei enthält kein Vorschaubild" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "%(number)s von %(total)s Bildern kopiert" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "Download von %s abgeschlossen" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "Laufwerk" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "Grösse" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "Fortschritt im Download" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "Vorschaubild kann nicht angezeigt werden" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "Es könnte defekt sein" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "Einige Einstellungen werden zurückgesetzt." + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" +"Eine neuere Version des Programms wurde bereits auf diesem Computer " +"aufgerufen.\n" +"\n" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" +"Die Voreinstellungen scheinen gültig zu sein, aber bitte überprüfen Sie " +"diese." + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "" +"Einige Voreinstellungen sind ungültig, sie werden auf die Standardwerte " +"zurückgesetzt." + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "Warnung:" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" +"Diese Version des Programms ist neuer als bis bisherige. Die " +"Voreinstellungen werden überprüft." + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "Die Voreinstellungen wurden geändert." + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" +"Diese Version des Programms ist neuer als bis bisherige. Die " +"Voreinstellungen wurden angepasst\n" +"Bitte überprüfen Sie diese." + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "Es mussten keine Voreinstellungen angepasst werden." + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" +"Die Version des Programms verwendet andere Voreinstellungen als die " +"bisherige Version. Einige der bestehenden Einstellungen sind ungültig und " +"werden auf die Standardwerte zurückgesetzt." + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "Bei der Verwendung von pynotify ist ein Problem aufgetreten." + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "Die Werte des pynotify Servers konnten nicht abgefragt werden." + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "und" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "Die Sicherungslaufwerke werden verwendet" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "Das Sicherungslaufwerk wird verwendet" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "Es wurden keine Sicherungslaufwerke gefunden" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "Die %(device)s gefunden auf Pfad %(path)s" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "Der automatische Downloadbeginn ist eingeschaltet" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "Der automatische Downloadbeginn ist ausgeschaltet" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "Verwende den manuell eingegebenen Pfad" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "Alle Downloads sind abgeschlossen" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "MB/s" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "Etwa 1 Sekunde verbleibend" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "Etwa %i Sekunden verbleibend" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "Etwa 1 Minute verbleibend" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Etwa %(minutes)i:%(seconds)02i Minuten verbleibend" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "Bilder heruntergeladen" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "Bilder übersprungen" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "_Download " + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "_Pause" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "Die Voreinstellungen wurden geändert." + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "Auf Wiedersehen" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" +"Zeige die Programminformationen an, wenn das Programm aus der Kommandozeile " +"aufgerufen wurde (Voreinstellung: %default)" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "Zeige Fehlermeldungen nur auf der Kommandozeile an" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "Anzeigen der gültigen Deteiendungen und beenden" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "und %s" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "Verwende" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "%s wird bereits ausgeführt" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "Datum Zeit" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "Text" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "Dateiname" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "Metadaten" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "Sequenzen" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "Bilddatum" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "Heute" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "Gestern" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "Name + Erweiterung" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "Name" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "Erweiterung" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "Bildnummer" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "Blende" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "ISO-Wert" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "Belichtungszeit" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "Brennweite" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "Kamerahersteller" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "Kameramodell" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "Kameramodell (kurz)" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "Kameramodell (kurz, Bindestriche)" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "Seriennummer" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "Anzahl der Auslösungen" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "Besitzername" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "Downloads heute" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "Sitzungsnummer" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "Nummer des Unterverzeichnisses" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "Gespeicherte Nummer" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "Vorlaufender Buchstabe" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "Alle Ziffern" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "Letzte Ziffer" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "Letzte 2 Ziffern" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "Letzte 3 Ziffern" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "Letze 4 Ziffern" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "Ursprüngliche Schreibweise" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "Grossschrift" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "Kleinschrift" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "Eine Ziffer" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "Zwei Ziffern" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "Drei Ziffern" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "Vier Ziffern" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "Fünf Ziffern" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "Sechs Ziffern" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "Hundertstelsekunden" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "JJJJMMTT" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "JJJJ-MM-TT" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "JJMMTT" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "JJ-MM-TT" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "MMTTJJJJ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "MMTTJJ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "MMTT" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "TTMMJJJJ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "TTMMJJ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "JJJJ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "JJ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "MM" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "TT" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "HHMMSS" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "HHMM" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" +"Voreinstellung '%(key)s' ist ungültig.\n" +"Erwarteter Wert %(value)s" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "Vorgaben für Wert '%(value)s' ist ungültig" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "Diese Voreinstellungen sind falsch formatiert:" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "Das Bild enthält keine Hunderstelsekunden-Informationen" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "%s Metadaten sind im Bild nicht vorhanden" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "" +"Fehler in den Datum/Zeit Informationen. Der Wert %s scheint ungültig zu sein" + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "" +"Erweiterung wurde angegeben, aber der Dateiname enthält keine Erweiterung" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "" +"Eine Bildnummer wurde angegeben, aber der Dateiname enthält keine Nummer" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "Ein Fehler ist aufgetreten bei der Erstellung des Namens mit %s" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Die Unterordnereinstellungen sollten nicht mit %s beginnen" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Die Unterordnereinstellungen sollten nicht mit %s enden" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" +"Die Unterordnereinstellungen sollten nicht zwei %s nacheinander enthalten" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr " hh:mm" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr ":" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "<b>Datensicherung</b>" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "<b>Kompatibilität mit anderen Betriebssystemen</b>" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "<b>Download Ordner</b>" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "<b>Download Unterverzeichnis</b>" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "<b>Beispiel</b>" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "<b>Laufwerke mit Bilddaten</b>" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "<b>Konfilkte der Bildernamen</b>" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "<b>Umbenennung von Bildern</b>" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "<b>Fehlende Sicherungslaufwerke</b>" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "<b>Programm Automatisierung</b>" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "<b>Sequenznummern</b>" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "<i>/medium/externeslaufwerk/Fotos</i>" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "<i>Beispiel: /home/user/Fotos</i>" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "<i>Beispiel:</i>" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "<i>Neu:</i>" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "<i>Original:</i>" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Automatisierung</span>" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Datensicherung</span>\t" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Download Verzeichnis</span>" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Fehlerbehandlung</span>" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Laufwerke</span>" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Umbenennung von Dateien</span>\t" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Einstellungen zur Umbenennung</span>" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "Füge eine eindeutige Information hinzu" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "Suche automatisch nach portablen Laufwerken" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "Suche automatisch nach Backuplaufwerken" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "Suche automatisch nach Laufwerken mit Bildern" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "Automatisierung" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "Datensicherung" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "Verzeichnis für Datensicherung:" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "Ziel der Datensicherung" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "Erstelle Sicherung der Bilder beim Herunterladen" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" +"Wählen Sie das Downloadverzeichnis. Unterverzeichnisse werden je nach " +"gewählten Einstellungen automatisch erzeugt." + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" +"Wählen Sie das Bild zu überspringen oder eine eindeutige Bezeichnung " +"einzufügen" + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "Copyright Damon Lynch 2007-09" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "Beginn des Tages:" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "Download / Pause" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "Downloadverzeichnis" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "Downloadverzeichnis:" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "Downloads heute:" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "Fehlerbehandlung" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "Fehlerprotokoll" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "Beende das Programm nach Abschluss des Downloads" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" +"Wählen Sie das genaue Verzeichnis für die Datensicherung, falls die " +"automatische Erkennung ausgeschaltet ist." + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" +"Wählen Sie das genaue Verzeichnis für die Bilder, falls die automatische " +"Erkennung ausgeschaltet ist." + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" +"Wenn Sie die automatische Erkennung für portable Geräte aktivieren, wird das " +"gesamte Gerät nach Fotos durchsucht. Bei sehr großen Datenträgern kann dies " +"eine Weile dauern." + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "Ignoriere" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "Laufwerke mit Bildern" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "Dateiumbenennung" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" +"Laufwerke mit Bilddaten sind Geräte, von denen Fotos heruntergeladen werden " +"können, wie Kameras, Speicherkarten oder portable Speichermedien.\n" +"\n" +"Sie können Bilder von mehreren Speichermedien gleichzeitig herunterladen.\n" +"\n" +"<i>Wenn das direkte Herunterladen von Ihrer Kamera langsam oder überhaupt " +"nicht funktioniert, versuchen Sie diese in den PTP Modus zu schalten. Sollte " +"das nicht möglich sein, verwenden Sie bitte einen Kartenleser.</i>" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "Bilder Quelle:" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "Importieren Sie Ihre Bilder effizient und zuverlässig" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "Überschreibe" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "Voreinstellungen: Rapid Photo Downloader" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "Optionen für die Umbenennung" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "Melden Sie eine Warnung" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "Melden Sie einen Fehler" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "Überspringe" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "Überspringe Download" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" +"Geben Sie ein Verzeichnis an, in welchem die Sicherungskopien auf dem " +"Laufwerk gespeichert werden.\n" +"<i>Hinweis: Diese Einstellung wird auch verwendet um festzulegen, ob das " +"Laufwerk für Sicherungskopien verwendet wird oder nicht. Bitte erstellen Sie " +"auf jedem Laufwerk, welches Sie zur Datensicherung verwenden wollen, einen " +"Ordner mit diesem Namen.</i>" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" +"Geben Sie die Zeit im 24-Stunden Format an, wann die Sequenznummer in " +"<i>Downloads heute</i> zurückgesetzt werden soll." + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" +"Gegen Sie an was geschehen soll, falls eine Datei oder eine Sicherungskopie " +"mit demselben Namen bereits existiert." + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "" +"Geben Sie an was geschehen soll, falls keine Sicherungslaufwerke vorhanden " +"sind." + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" +"Geben Sie an was geschehen soll, wenn die Verzeichnisse Zeichen enthalten, " +"welche von anderen Betriebssystemen nicht unterstützt werden." + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "Beginn des Downloads bei Programmstart" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "Beginn des Downloads beim Einfügen von Bilderlaufwerken" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "Gespeicherte Nummer" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "Entferne nicht kompatible Zeichen" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "Aufwerfen des Bildlaufwerks nach Beendigung des Downloads" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" +"Während der Datensicherung können bestehende Bilder auf dem " +"Sicherungslaufwerk überschrieben oder übersprungen werden." + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" +"Sie können Bilder während des Herunterladens an mehrere Orten sichern, z.B. " +"auf externe Festplatten." + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "_Heruntergeladene Dateien nicht mehr anzeigen" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "_Fehlerprotokoll" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "_Online Hilfe ..." + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "_Hilfe" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "_Machen Sie eine Spende" + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "_Fotos" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "_Problemmeldung" + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "_Vorschaubilder" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "_Übersetzung der Applikation" + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "_Ansicht" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "Für die Übersetzung bitte ignorieren" + +#~ msgid "Resequence" +#~ msgstr "Neunummerierung" + +#~ msgid "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>" +#~ msgstr "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>" + +#~ msgid "gtk-help" +#~ msgstr "gtk-help" diff --git a/po/en_AU.po b/po/en_AU.po new file mode 100644 index 0000000..388445a --- /dev/null +++ b/po/en_AU.po @@ -0,0 +1,1173 @@ +# English (Australia) translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-19 18:41+0800\n" +"PO-Revision-Date: 2009-05-19 11:02+0000\n" +"Last-Translator: Damon Lynch <damonlynch@gmail.com>\n" +"Language-Team: English (Australia) <en_AU@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-05-19 11:36+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: rapid/rapid.py:99 rapid/glade3/rapid.glade.h:59 +msgid "Rapid Photo Downloader" +msgstr "" + +#: rapid/rapid.py:399 +msgid "Invalid Downloads Today value.\n" +msgstr "" + +#: rapid/rapid.py:400 +msgid "Resetting value to zero.\n" +msgstr "" + +#: rapid/rapid.py:439 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "" + +#: rapid/rapid.py:440 +msgid "Resetting to midnight.\n" +msgstr "" + +#: rapid/rapid.py:456 +msgid "Error in Image Rename preferences" +msgstr "" + +#: rapid/rapid.py:465 rapid/rapid.py:1127 +msgid "Sorry,these preferences contain an error:\n" +msgstr "" + +#: rapid/rapid.py:476 +msgid "Resetting to default values." +msgstr "" + +#: rapid/rapid.py:587 +msgid "Error in Download Subfolder preferences" +msgstr "" + +#: rapid/rapid.py:704 +msgid "Select a folder to download photos to" +msgstr "" + +#: rapid/rapid.py:751 +msgid "Select an image folder" +msgstr "" + +#: rapid/rapid.py:773 +msgid "Select a folder in which to backup images" +msgstr "" + +#: rapid/rapid.py:861 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" + +#: rapid/rapid.py:882 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" + +#: rapid/rapid.py:884 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "" + +#. this value is used as an example device when automatic backup device detection is enabled +#: rapid/rapid.py:1057 +msgid "externaldrive1" +msgstr "" + +#. this value is used as an example device when automatic backup device detection is enabled +#: rapid/rapid.py:1059 +msgid "externaldrive2" +msgstr "" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1116 +msgid "scanning..." +msgstr "" + +#: rapid/rapid.py:1223 rapid/rapid.py:1788 +#, python-format +msgid "0 of %s images copied" +msgstr "" + +#: rapid/rapid.py:1228 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" + +#: rapid/rapid.py:1234 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "" + +#: rapid/rapid.py:1265 +msgid "Image filename could not be generated" +msgstr "" + +#: rapid/rapid.py:1266 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1270 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" + +#: rapid/rapid.py:1271 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1280 +msgid "Could not open image" +msgstr "" + +#: rapid/rapid.py:1281 +#, python-format +msgid "Source: %s" +msgstr "" + +#: rapid/rapid.py:1290 +msgid "Image has no metadata" +msgstr "" + +#: rapid/rapid.py:1291 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" + +#: rapid/rapid.py:1303 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" + +#: rapid/rapid.py:1304 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1356 rapid/rapid.py:1384 rapid/rapid.py:1403 +#: rapid/rapid.py:1465 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" + +#: rapid/rapid.py:1405 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1422 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" + +#: rapid/rapid.py:1427 rapid/rapid.py:1433 +msgid "Download copying error" +msgstr "" + +#: rapid/rapid.py:1428 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" + +#: rapid/rapid.py:1430 rapid/rapid.py:1503 +msgid "The image was not copied." +msgstr "" + +#: rapid/rapid.py:1464 +msgid "Backup image already exists" +msgstr "" + +#: rapid/rapid.py:1492 rapid/rapid.py:1500 rapid/rapid.py:1506 +msgid "Backing up error" +msgstr "" + +#: rapid/rapid.py:1493 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" + +#: rapid/rapid.py:1501 rapid/rapid.py:1507 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" + +#. The device was automatically unmounted +#: rapid/rapid.py:1520 +msgid "The device can now be safely removed" +msgstr "" + +#: rapid/rapid.py:1524 +#, python-format +msgid "%s images downloaded" +msgstr "" + +#: rapid/rapid.py:1526 +#, python-format +msgid "%s images skipped" +msgstr "" + +#: rapid/rapid.py:1532 rapid/rapid.py:2599 +msgid "warnings" +msgstr "" + +#: rapid/rapid.py:1534 rapid/rapid.py:2601 +msgid "errors" +msgstr "" + +#: rapid/rapid.py:1548 +msgid "Download cannot proceed" +msgstr "" + +#: rapid/rapid.py:1548 +msgid "" +"There is an error in the program preferences.\n" +"Please check preferences, restart the program, and try again." +msgstr "" + +#: rapid/rapid.py:1561 +msgid "Backup device missing" +msgstr "" + +#: rapid/rapid.py:1561 +msgid "No backup device was detected." +msgstr "" + +#: rapid/rapid.py:1565 +msgid "This device has no images to download from." +msgstr "" + +#: rapid/rapid.py:1586 +#, python-format +msgid "Download has started from %s" +msgstr "" + +#: rapid/rapid.py:1623 +msgid "Image skipped" +msgstr "" + +#: rapid/rapid.py:1624 +msgid "Image overwritten" +msgstr "" + +#: rapid/rapid.py:1625 +msgid "Image already exists" +msgstr "" + +#: rapid/rapid.py:1670 +msgid "Image has no thumbnail" +msgstr "" + +#: rapid/rapid.py:1680 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "" + +#: rapid/rapid.py:1696 +#, python-format +msgid "Download complete from %s" +msgstr "" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1772 +msgid "Device" +msgstr "" + +#. Size refers to the total size of images on the device +#: rapid/rapid.py:1777 +msgid "Size" +msgstr "" + +#: rapid/rapid.py:1780 +msgid "Download Progress" +msgstr "" + +#: rapid/rapid.py:1896 rapid/rapid.py:1902 +msgid "Thumbnail cannot be displayed" +msgstr "" + +#: rapid/rapid.py:1897 rapid/rapid.py:1903 +msgid "It may be corrupted" +msgstr "" + +#: rapid/rapid.py:2150 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" + +#: rapid/rapid.py:2152 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" + +#: rapid/rapid.py:2154 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "" + +#: rapid/rapid.py:2155 +msgid "Warning:" +msgstr "" + +#: rapid/rapid.py:2160 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" + +#: rapid/rapid.py:2167 +msgid "Preferences were modified." +msgstr "" + +#: rapid/rapid.py:2168 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" + +#: rapid/rapid.py:2172 +msgid "No preferences needed to be changed." +msgstr "" + +#: rapid/rapid.py:2174 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" + +#: rapid/rapid.py:2182 +msgid "Problem using pynotify." +msgstr "" + +#: rapid/rapid.py:2198 +msgid "Failed to receive pynotify server capabilities." +msgstr "" + +#: rapid/rapid.py:2236 +msgid "and" +msgstr "" + +#: rapid/rapid.py:2241 +msgid "Using backup devices" +msgstr "" + +#: rapid/rapid.py:2243 +msgid "Using backup device" +msgstr "" + +#: rapid/rapid.py:2245 +msgid "No backup devices detected" +msgstr "" + +#: rapid/rapid.py:2380 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "" + +#: rapid/rapid.py:2384 +msgid "Automatically start download is true" +msgstr "" + +#: rapid/rapid.py:2386 +msgid "Automatically start download is false" +msgstr "" + +#: rapid/rapid.py:2434 +msgid "Using manually specified path" +msgstr "" + +#: rapid/rapid.py:2548 rapid/rapid.py:2594 +msgid "All downloads complete" +msgstr "" + +#: rapid/rapid.py:2562 +msgid "MB/s" +msgstr "" + +#: rapid/rapid.py:2572 +msgid "About 1 second remaining" +msgstr "" + +#: rapid/rapid.py:2574 +#, python-format +msgid "About %i seconds remaining" +msgstr "" + +#: rapid/rapid.py:2576 +msgid "About 1 minute remaining" +msgstr "" + +#: rapid/rapid.py:2578 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "" + +#: rapid/rapid.py:2595 +msgid "images downloaded" +msgstr "" + +#: rapid/rapid.py:2597 +msgid "images skipped" +msgstr "" + +#. note the space at the end of the label, need it to meet HIG! :( +#: rapid/rapid.py:2685 +msgid "_Download " +msgstr "" + +#. note the space at the end of the label, need it to meet HIG! :( +#: rapid/rapid.py:2695 +msgid "_Pause" +msgstr "" + +#: rapid/rapid.py:2752 +msgid "Preferences were changed." +msgstr "" + +#: rapid/rapid.py:2883 +msgid "Goodbye" +msgstr "" + +#: rapid/rapid.py:2892 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" + +#: rapid/rapid.py:2893 +msgid "only output errors to the command line" +msgstr "" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:2895 +msgid "list image file extensions the program recognizes and exit" +msgstr "list image file extensions the program recognises and exit" + +#: rapid/rapid.py:2908 +#, python-format +msgid "and %s" +msgstr "" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:2913 rapid/rapid.py:2916 +msgid "Using" +msgstr "" + +#. this application is already running +#: rapid/rapid.py:2930 +#, python-format +msgid "%s is already running" +msgstr "" + +#: rapid/renamesubfolderprefs.py:173 +msgid "Date time" +msgstr "" + +#: rapid/renamesubfolderprefs.py:174 +msgid "Text" +msgstr "" + +#: rapid/renamesubfolderprefs.py:175 +msgid "Filename" +msgstr "" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Metadata" +msgstr "" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Sequences" +msgstr "" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Image date" +msgstr "" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Today" +msgstr "" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Yesterday" +msgstr "" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Name + extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Name" +msgstr "" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:184 +msgid "Image number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:185 +msgid "Aperture" +msgstr "" + +#: rapid/renamesubfolderprefs.py:186 +msgid "ISO" +msgstr "" + +#: rapid/renamesubfolderprefs.py:187 +msgid "Exposure time" +msgstr "" + +#: rapid/renamesubfolderprefs.py:188 +msgid "Focal length" +msgstr "" + +#: rapid/renamesubfolderprefs.py:189 +msgid "Camera make" +msgstr "" + +#: rapid/renamesubfolderprefs.py:190 +msgid "Camera model" +msgstr "" + +#: rapid/renamesubfolderprefs.py:191 +msgid "Short camera model" +msgstr "" + +#: rapid/renamesubfolderprefs.py:192 +msgid "Hyphenated short camera model" +msgstr "" + +#: rapid/renamesubfolderprefs.py:193 +msgid "Serial number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:194 +msgid "Shutter count" +msgstr "" + +#: rapid/renamesubfolderprefs.py:195 +msgid "Owner name" +msgstr "" + +#: rapid/renamesubfolderprefs.py:196 +msgid "Downloads today" +msgstr "" + +#: rapid/renamesubfolderprefs.py:197 +msgid "Session number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:198 +msgid "Subfolder number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:199 +msgid "Stored number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:200 +msgid "Sequence letter" +msgstr "" + +#: rapid/renamesubfolderprefs.py:201 +msgid "All digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:202 +msgid "Last digit" +msgstr "" + +#: rapid/renamesubfolderprefs.py:203 +msgid "Last 2 digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:204 +msgid "Last 3 digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:205 +msgid "Last 4 digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:206 +msgid "Original Case" +msgstr "" + +#: rapid/renamesubfolderprefs.py:207 +msgid "UPPERCASE" +msgstr "" + +#: rapid/renamesubfolderprefs.py:208 +msgid "lowercase" +msgstr "" + +#: rapid/renamesubfolderprefs.py:209 +msgid "One digit" +msgstr "" + +#: rapid/renamesubfolderprefs.py:210 +msgid "Two digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:211 +msgid "Three digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:212 +msgid "Four digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:213 +msgid "Five digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:214 +msgid "Six digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:215 +msgid "Subseconds" +msgstr "" + +#: rapid/renamesubfolderprefs.py:216 +msgid "YYYYMMDD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:217 +msgid "YYYY-MM-DD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:218 +msgid "YYMMDD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:219 +msgid "YY-MM-DD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:220 +msgid "MMDDYYYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:221 +msgid "MMDDYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:222 +msgid "MMDD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:223 +msgid "DDMMYYYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:224 +msgid "DDMMYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:225 +msgid "YYYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:226 +msgid "YY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:227 +msgid "MM" +msgstr "" + +#: rapid/renamesubfolderprefs.py:228 +msgid "DD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:229 +msgid "HHMMSS" +msgstr "" + +#: rapid/renamesubfolderprefs.py:230 +msgid "HHMM" +msgstr "" + +#: rapid/renamesubfolderprefs.py:599 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:606 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "" + +#: rapid/renamesubfolderprefs.py:610 +msgid "These preferences are not well formed:" +msgstr "" + +#: rapid/renamesubfolderprefs.py:710 +msgid "Subsecond metadata not present in image" +msgstr "" + +#: rapid/renamesubfolderprefs.py:713 rapid/renamesubfolderprefs.py:836 +#, python-format +msgid "%s metadata is not present in image" +msgstr "" + +#: rapid/renamesubfolderprefs.py:728 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "" + +#: rapid/renamesubfolderprefs.py:759 +msgid "extension was specified but image name has no extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:763 +msgid "image number was specified but image filename has no number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:948 +#, python-format +msgid "error generating name with component %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1264 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1266 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1270 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr "" + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr "" + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr "" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr "" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download Folder" +msgstr "" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download folder:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Downloads today:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Error Handling" +msgstr "" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Log" +msgstr "" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Exit program after completion of successful download" +msgstr "" + +#: rapid/glade3/rapid.glade.h:47 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" + +#: rapid/glade3/rapid.glade.h:48 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" + +#: rapid/glade3/rapid.glade.h:49 +msgid "Ignore" +msgstr "" + +#: rapid/glade3/rapid.glade.h:50 +msgid "Image Devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:51 +msgid "Image Rename" +msgstr "" + +#: rapid/glade3/rapid.glade.h:52 +msgid "" +"Image devices are devices from which to download photos, such as memory " +"cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously." +msgstr "" + +#: rapid/glade3/rapid.glade.h:55 +msgid "Image location:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:56 +msgid "Import your images efficiently and reliably" +msgstr "" + +#: rapid/glade3/rapid.glade.h:57 +msgid "Overwrite" +msgstr "" + +#: rapid/glade3/rapid.glade.h:58 +msgid "Preferences: Rapid Photo Downloader" +msgstr "" + +#: rapid/glade3/rapid.glade.h:60 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" + +#: rapid/glade3/rapid.glade.h:65 +msgid "Rename Options" +msgstr "" + +#: rapid/glade3/rapid.glade.h:66 +msgid "Report a warning" +msgstr "" + +#: rapid/glade3/rapid.glade.h:67 +msgid "Report an error" +msgstr "" + +#: rapid/glade3/rapid.glade.h:68 +msgid "Skip" +msgstr "" + +#: rapid/glade3/rapid.glade.h:69 +msgid "Skip download" +msgstr "" + +#: rapid/glade3/rapid.glade.h:70 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:73 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" + +#: rapid/glade3/rapid.glade.h:75 +msgid "Specify what to do when there are no backup devices." +msgstr "" + +#: rapid/glade3/rapid.glade.h:76 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" + +#: rapid/glade3/rapid.glade.h:77 +msgid "Start downloading at program startup" +msgstr "" + +#: rapid/glade3/rapid.glade.h:78 +msgid "Start downloading upon image device insertion" +msgstr "" + +#: rapid/glade3/rapid.glade.h:79 +msgid "Stored number:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:80 +msgid "Strip incompatible characters" +msgstr "" + +#: rapid/glade3/rapid.glade.h:81 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "" + +#: rapid/glade3/rapid.glade.h:82 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" + +#: rapid/glade3/rapid.glade.h:83 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" + +#: rapid/glade3/rapid.glade.h:84 +msgid "_Clear Completed Downloads" +msgstr "" + +#: rapid/glade3/rapid.glade.h:85 +msgid "_Error Log" +msgstr "" + +#: rapid/glade3/rapid.glade.h:86 +msgid "_Get Help Online..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:87 +msgid "_Help" +msgstr "" + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Make a Donation..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Photos" +msgstr "" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Report a Problem..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Thumbnails" +msgstr "" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_View" +msgstr "" + +#: rapid/glade3/rapid.glade.h:94 +msgid "translator-credits" +msgstr "" +"Launchpad Contributions:\n" +" Damon Lynch https://launchpad.net/~dlynch3" + +#: rapid/glade3/rapid.glade.h:95 +msgid "translators please ignore this" +msgstr "" diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 0000000..fe586e9 --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,1173 @@ +# English (United Kingdom) translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-19 18:41+0800\n" +"PO-Revision-Date: 2009-05-19 11:10+0000\n" +"Last-Translator: Damon Lynch <damonlynch@gmail.com>\n" +"Language-Team: English (United Kingdom) <en_GB@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-05-19 11:36+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: rapid/rapid.py:99 rapid/glade3/rapid.glade.h:59 +msgid "Rapid Photo Downloader" +msgstr "" + +#: rapid/rapid.py:399 +msgid "Invalid Downloads Today value.\n" +msgstr "" + +#: rapid/rapid.py:400 +msgid "Resetting value to zero.\n" +msgstr "" + +#: rapid/rapid.py:439 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "" + +#: rapid/rapid.py:440 +msgid "Resetting to midnight.\n" +msgstr "" + +#: rapid/rapid.py:456 +msgid "Error in Image Rename preferences" +msgstr "" + +#: rapid/rapid.py:465 rapid/rapid.py:1127 +msgid "Sorry,these preferences contain an error:\n" +msgstr "" + +#: rapid/rapid.py:476 +msgid "Resetting to default values." +msgstr "" + +#: rapid/rapid.py:587 +msgid "Error in Download Subfolder preferences" +msgstr "" + +#: rapid/rapid.py:704 +msgid "Select a folder to download photos to" +msgstr "" + +#: rapid/rapid.py:751 +msgid "Select an image folder" +msgstr "" + +#: rapid/rapid.py:773 +msgid "Select a folder in which to backup images" +msgstr "" + +#: rapid/rapid.py:861 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" + +#: rapid/rapid.py:882 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" + +#: rapid/rapid.py:884 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "" + +#. this value is used as an example device when automatic backup device detection is enabled +#: rapid/rapid.py:1057 +msgid "externaldrive1" +msgstr "" + +#. this value is used as an example device when automatic backup device detection is enabled +#: rapid/rapid.py:1059 +msgid "externaldrive2" +msgstr "" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1116 +msgid "scanning..." +msgstr "" + +#: rapid/rapid.py:1223 rapid/rapid.py:1788 +#, python-format +msgid "0 of %s images copied" +msgstr "" + +#: rapid/rapid.py:1228 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" + +#: rapid/rapid.py:1234 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "" + +#: rapid/rapid.py:1265 +msgid "Image filename could not be generated" +msgstr "" + +#: rapid/rapid.py:1266 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1270 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" + +#: rapid/rapid.py:1271 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1280 +msgid "Could not open image" +msgstr "" + +#: rapid/rapid.py:1281 +#, python-format +msgid "Source: %s" +msgstr "" + +#: rapid/rapid.py:1290 +msgid "Image has no metadata" +msgstr "" + +#: rapid/rapid.py:1291 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" + +#: rapid/rapid.py:1303 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" + +#: rapid/rapid.py:1304 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1356 rapid/rapid.py:1384 rapid/rapid.py:1403 +#: rapid/rapid.py:1465 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" + +#: rapid/rapid.py:1405 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1422 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" + +#: rapid/rapid.py:1427 rapid/rapid.py:1433 +msgid "Download copying error" +msgstr "" + +#: rapid/rapid.py:1428 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" + +#: rapid/rapid.py:1430 rapid/rapid.py:1503 +msgid "The image was not copied." +msgstr "" + +#: rapid/rapid.py:1464 +msgid "Backup image already exists" +msgstr "" + +#: rapid/rapid.py:1492 rapid/rapid.py:1500 rapid/rapid.py:1506 +msgid "Backing up error" +msgstr "" + +#: rapid/rapid.py:1493 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" + +#: rapid/rapid.py:1501 rapid/rapid.py:1507 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" + +#. The device was automatically unmounted +#: rapid/rapid.py:1520 +msgid "The device can now be safely removed" +msgstr "" + +#: rapid/rapid.py:1524 +#, python-format +msgid "%s images downloaded" +msgstr "" + +#: rapid/rapid.py:1526 +#, python-format +msgid "%s images skipped" +msgstr "" + +#: rapid/rapid.py:1532 rapid/rapid.py:2599 +msgid "warnings" +msgstr "" + +#: rapid/rapid.py:1534 rapid/rapid.py:2601 +msgid "errors" +msgstr "" + +#: rapid/rapid.py:1548 +msgid "Download cannot proceed" +msgstr "" + +#: rapid/rapid.py:1548 +msgid "" +"There is an error in the program preferences.\n" +"Please check preferences, restart the program, and try again." +msgstr "" + +#: rapid/rapid.py:1561 +msgid "Backup device missing" +msgstr "" + +#: rapid/rapid.py:1561 +msgid "No backup device was detected." +msgstr "" + +#: rapid/rapid.py:1565 +msgid "This device has no images to download from." +msgstr "" + +#: rapid/rapid.py:1586 +#, python-format +msgid "Download has started from %s" +msgstr "" + +#: rapid/rapid.py:1623 +msgid "Image skipped" +msgstr "" + +#: rapid/rapid.py:1624 +msgid "Image overwritten" +msgstr "" + +#: rapid/rapid.py:1625 +msgid "Image already exists" +msgstr "" + +#: rapid/rapid.py:1670 +msgid "Image has no thumbnail" +msgstr "" + +#: rapid/rapid.py:1680 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "" + +#: rapid/rapid.py:1696 +#, python-format +msgid "Download complete from %s" +msgstr "" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1772 +msgid "Device" +msgstr "" + +#. Size refers to the total size of images on the device +#: rapid/rapid.py:1777 +msgid "Size" +msgstr "" + +#: rapid/rapid.py:1780 +msgid "Download Progress" +msgstr "" + +#: rapid/rapid.py:1896 rapid/rapid.py:1902 +msgid "Thumbnail cannot be displayed" +msgstr "" + +#: rapid/rapid.py:1897 rapid/rapid.py:1903 +msgid "It may be corrupted" +msgstr "" + +#: rapid/rapid.py:2150 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" + +#: rapid/rapid.py:2152 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" + +#: rapid/rapid.py:2154 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "" + +#: rapid/rapid.py:2155 +msgid "Warning:" +msgstr "" + +#: rapid/rapid.py:2160 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" + +#: rapid/rapid.py:2167 +msgid "Preferences were modified." +msgstr "" + +#: rapid/rapid.py:2168 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" + +#: rapid/rapid.py:2172 +msgid "No preferences needed to be changed." +msgstr "" + +#: rapid/rapid.py:2174 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" + +#: rapid/rapid.py:2182 +msgid "Problem using pynotify." +msgstr "" + +#: rapid/rapid.py:2198 +msgid "Failed to receive pynotify server capabilities." +msgstr "" + +#: rapid/rapid.py:2236 +msgid "and" +msgstr "" + +#: rapid/rapid.py:2241 +msgid "Using backup devices" +msgstr "" + +#: rapid/rapid.py:2243 +msgid "Using backup device" +msgstr "" + +#: rapid/rapid.py:2245 +msgid "No backup devices detected" +msgstr "" + +#: rapid/rapid.py:2380 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "" + +#: rapid/rapid.py:2384 +msgid "Automatically start download is true" +msgstr "" + +#: rapid/rapid.py:2386 +msgid "Automatically start download is false" +msgstr "" + +#: rapid/rapid.py:2434 +msgid "Using manually specified path" +msgstr "" + +#: rapid/rapid.py:2548 rapid/rapid.py:2594 +msgid "All downloads complete" +msgstr "" + +#: rapid/rapid.py:2562 +msgid "MB/s" +msgstr "" + +#: rapid/rapid.py:2572 +msgid "About 1 second remaining" +msgstr "" + +#: rapid/rapid.py:2574 +#, python-format +msgid "About %i seconds remaining" +msgstr "" + +#: rapid/rapid.py:2576 +msgid "About 1 minute remaining" +msgstr "" + +#: rapid/rapid.py:2578 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "" + +#: rapid/rapid.py:2595 +msgid "images downloaded" +msgstr "" + +#: rapid/rapid.py:2597 +msgid "images skipped" +msgstr "" + +#. note the space at the end of the label, need it to meet HIG! :( +#: rapid/rapid.py:2685 +msgid "_Download " +msgstr "" + +#. note the space at the end of the label, need it to meet HIG! :( +#: rapid/rapid.py:2695 +msgid "_Pause" +msgstr "" + +#: rapid/rapid.py:2752 +msgid "Preferences were changed." +msgstr "" + +#: rapid/rapid.py:2883 +msgid "Goodbye" +msgstr "" + +#: rapid/rapid.py:2892 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" + +#: rapid/rapid.py:2893 +msgid "only output errors to the command line" +msgstr "" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:2895 +msgid "list image file extensions the program recognizes and exit" +msgstr "list image file extensions the program recognises and exit" + +#: rapid/rapid.py:2908 +#, python-format +msgid "and %s" +msgstr "" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:2913 rapid/rapid.py:2916 +msgid "Using" +msgstr "" + +#. this application is already running +#: rapid/rapid.py:2930 +#, python-format +msgid "%s is already running" +msgstr "" + +#: rapid/renamesubfolderprefs.py:173 +msgid "Date time" +msgstr "" + +#: rapid/renamesubfolderprefs.py:174 +msgid "Text" +msgstr "" + +#: rapid/renamesubfolderprefs.py:175 +msgid "Filename" +msgstr "" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Metadata" +msgstr "" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Sequences" +msgstr "" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Image date" +msgstr "" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Today" +msgstr "" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Yesterday" +msgstr "" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Name + extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Name" +msgstr "" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:184 +msgid "Image number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:185 +msgid "Aperture" +msgstr "" + +#: rapid/renamesubfolderprefs.py:186 +msgid "ISO" +msgstr "" + +#: rapid/renamesubfolderprefs.py:187 +msgid "Exposure time" +msgstr "" + +#: rapid/renamesubfolderprefs.py:188 +msgid "Focal length" +msgstr "" + +#: rapid/renamesubfolderprefs.py:189 +msgid "Camera make" +msgstr "" + +#: rapid/renamesubfolderprefs.py:190 +msgid "Camera model" +msgstr "" + +#: rapid/renamesubfolderprefs.py:191 +msgid "Short camera model" +msgstr "" + +#: rapid/renamesubfolderprefs.py:192 +msgid "Hyphenated short camera model" +msgstr "" + +#: rapid/renamesubfolderprefs.py:193 +msgid "Serial number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:194 +msgid "Shutter count" +msgstr "" + +#: rapid/renamesubfolderprefs.py:195 +msgid "Owner name" +msgstr "" + +#: rapid/renamesubfolderprefs.py:196 +msgid "Downloads today" +msgstr "" + +#: rapid/renamesubfolderprefs.py:197 +msgid "Session number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:198 +msgid "Subfolder number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:199 +msgid "Stored number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:200 +msgid "Sequence letter" +msgstr "" + +#: rapid/renamesubfolderprefs.py:201 +msgid "All digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:202 +msgid "Last digit" +msgstr "" + +#: rapid/renamesubfolderprefs.py:203 +msgid "Last 2 digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:204 +msgid "Last 3 digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:205 +msgid "Last 4 digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:206 +msgid "Original Case" +msgstr "" + +#: rapid/renamesubfolderprefs.py:207 +msgid "UPPERCASE" +msgstr "" + +#: rapid/renamesubfolderprefs.py:208 +msgid "lowercase" +msgstr "" + +#: rapid/renamesubfolderprefs.py:209 +msgid "One digit" +msgstr "" + +#: rapid/renamesubfolderprefs.py:210 +msgid "Two digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:211 +msgid "Three digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:212 +msgid "Four digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:213 +msgid "Five digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:214 +msgid "Six digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:215 +msgid "Subseconds" +msgstr "" + +#: rapid/renamesubfolderprefs.py:216 +msgid "YYYYMMDD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:217 +msgid "YYYY-MM-DD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:218 +msgid "YYMMDD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:219 +msgid "YY-MM-DD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:220 +msgid "MMDDYYYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:221 +msgid "MMDDYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:222 +msgid "MMDD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:223 +msgid "DDMMYYYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:224 +msgid "DDMMYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:225 +msgid "YYYY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:226 +msgid "YY" +msgstr "" + +#: rapid/renamesubfolderprefs.py:227 +msgid "MM" +msgstr "" + +#: rapid/renamesubfolderprefs.py:228 +msgid "DD" +msgstr "" + +#: rapid/renamesubfolderprefs.py:229 +msgid "HHMMSS" +msgstr "" + +#: rapid/renamesubfolderprefs.py:230 +msgid "HHMM" +msgstr "" + +#: rapid/renamesubfolderprefs.py:599 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:606 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "" + +#: rapid/renamesubfolderprefs.py:610 +msgid "These preferences are not well formed:" +msgstr "" + +#: rapid/renamesubfolderprefs.py:710 +msgid "Subsecond metadata not present in image" +msgstr "" + +#: rapid/renamesubfolderprefs.py:713 rapid/renamesubfolderprefs.py:836 +#, python-format +msgid "%s metadata is not present in image" +msgstr "" + +#: rapid/renamesubfolderprefs.py:728 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "" + +#: rapid/renamesubfolderprefs.py:759 +msgid "extension was specified but image name has no extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:763 +msgid "image number was specified but image filename has no number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:948 +#, python-format +msgid "error generating name with component %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1264 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1266 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1270 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr "" + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr "" + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr "" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr "" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download Folder" +msgstr "" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download folder:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Downloads today:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Error Handling" +msgstr "" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Log" +msgstr "" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Exit program after completion of successful download" +msgstr "" + +#: rapid/glade3/rapid.glade.h:47 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" + +#: rapid/glade3/rapid.glade.h:48 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" + +#: rapid/glade3/rapid.glade.h:49 +msgid "Ignore" +msgstr "" + +#: rapid/glade3/rapid.glade.h:50 +msgid "Image Devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:51 +msgid "Image Rename" +msgstr "" + +#: rapid/glade3/rapid.glade.h:52 +msgid "" +"Image devices are devices from which to download photos, such as memory " +"cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously." +msgstr "" + +#: rapid/glade3/rapid.glade.h:55 +msgid "Image location:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:56 +msgid "Import your images efficiently and reliably" +msgstr "" + +#: rapid/glade3/rapid.glade.h:57 +msgid "Overwrite" +msgstr "" + +#: rapid/glade3/rapid.glade.h:58 +msgid "Preferences: Rapid Photo Downloader" +msgstr "" + +#: rapid/glade3/rapid.glade.h:60 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" + +#: rapid/glade3/rapid.glade.h:65 +msgid "Rename Options" +msgstr "" + +#: rapid/glade3/rapid.glade.h:66 +msgid "Report a warning" +msgstr "" + +#: rapid/glade3/rapid.glade.h:67 +msgid "Report an error" +msgstr "" + +#: rapid/glade3/rapid.glade.h:68 +msgid "Skip" +msgstr "" + +#: rapid/glade3/rapid.glade.h:69 +msgid "Skip download" +msgstr "" + +#: rapid/glade3/rapid.glade.h:70 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:73 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" + +#: rapid/glade3/rapid.glade.h:75 +msgid "Specify what to do when there are no backup devices." +msgstr "" + +#: rapid/glade3/rapid.glade.h:76 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" + +#: rapid/glade3/rapid.glade.h:77 +msgid "Start downloading at program startup" +msgstr "" + +#: rapid/glade3/rapid.glade.h:78 +msgid "Start downloading upon image device insertion" +msgstr "" + +#: rapid/glade3/rapid.glade.h:79 +msgid "Stored number:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:80 +msgid "Strip incompatible characters" +msgstr "" + +#: rapid/glade3/rapid.glade.h:81 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "" + +#: rapid/glade3/rapid.glade.h:82 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" + +#: rapid/glade3/rapid.glade.h:83 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" + +#: rapid/glade3/rapid.glade.h:84 +msgid "_Clear Completed Downloads" +msgstr "" + +#: rapid/glade3/rapid.glade.h:85 +msgid "_Error Log" +msgstr "" + +#: rapid/glade3/rapid.glade.h:86 +msgid "_Get Help Online..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:87 +msgid "_Help" +msgstr "" + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Make a Donation..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Photos" +msgstr "" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Report a Problem..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Thumbnails" +msgstr "" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_View" +msgstr "" + +#: rapid/glade3/rapid.glade.h:94 +msgid "translator-credits" +msgstr "" +"Launchpad Contributions:\n" +" Damon Lynch https://launchpad.net/~dlynch3" + +#: rapid/glade3/rapid.glade.h:95 +msgid "translators please ignore this" +msgstr "" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..a8b471f --- /dev/null +++ b/po/es.po @@ -0,0 +1,1432 @@ +# Spanish translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: 2009-05-30 21:05+0000\n" +"Last-Translator: Abel O'Rian <abel.orian@gmail.com>\n" +"Language-Team: Spanish <es@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-05-31 13:32+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "Rapid Photo Downloader" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "Valor inválido de descargas de hoy.\n" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "Restablecer valores a cero.\n" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "'Inicio de día' valor corrupto.\n" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "Restablecer a medianoche.\n" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "Error en las preferencias de Renombrar Imagen" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "Lo siento, pero estas preferencias contienen un error:\n" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "Restablecer a los valores por defecto." + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "Error en subcarpeta de descargas" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "Seleccionar una carpeta para descargar las fotos" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "Seleccionar una carpeta de imágenes" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "Seleccione una carpeta para respaldar las imágenes" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Aviso:</b> No hay suficientes metadatos para poder generar el nombre. " +"Por favor, use las opciones de renombre.</i>" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Aviso:</b> No hay suficientes metadatos para poder generar las " +"subcarpetas. Por favor, use opciones de renombre.</i>" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Ejemplo: %s</i>" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "" +"Las preferencias de subcarpeta tienen algunos valores removidos " +"innecesariamente." + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" +"Las preferencias de subcarpeta ingresadas son inválidas y no pueden ser " +"usadas.\n" +"Estas serán restablecidas a los valores por defecto." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "dispositivoexterno1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "dispositivoexterno2" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "explorando..." + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "Hay un error en las preferencis del programa." + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" +"\n" +"Por favor revise las preferencia, reinicie el programa, y pruebe de nuevo." + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "No se puede proceder con la descarga" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "0 de %s imagenes copiadas" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" +"Exploración del dispositivo completada: encontradas %(number)s imágenes en " +"%(device)s" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "" +"Exploración del dispositivo completada: no se han encontrado imágenes en %s" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "Archivo de imagen no se ha generado" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" +"Origen: %(source)s\n" +"Problema: %(problem)s" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"El nombre de la imagen no pudo ser generado correctamente. Revise que hayan " +"suficientes metadatos en la imagen." + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" +"Origen: %(source)s\n" +"Destino: %(destination)s\n" +"Problema: %(problem)s" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "No se pudo abrir la imagen" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "Origen: %s" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "La imagen no tiene metadatos" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" +"Metadatos son esenciales para generar subcarpetas/nombres de imagen.\n" +"Destino: %s" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"El nombre de la subcarpeta no puede ser generado correctamente. Compruebe " +"que hay suficiente metadatos en la imagen." + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" +"Subcarpeta: %(subfolder)s\n" +"Imagen: %(image)s\n" +"Problema: %(problem)s" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Origen: %(source)s\n" +"Destino: %(destination)s" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "Identificador único '%s' agregado" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" +"Ha empezado un nuevo día - restableciendo los números de secuencia de " +"'Descargas del día'" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "Error al copiar la descarga" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" +"Origen: %(source)s\n" +"Destino: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "La imagen no fue copiada." + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "La copia de seguridad de la imagen ya existe" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "Error en copia de seguridad" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"El directorio de destino no pudo ser creado\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Origen: %(source)s\n" +"Destino: %(destination)s\n" +"Error: %(errno)s %(strerror)s" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "El dispositivo ya se puede extraer de forma segura" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "%s imágenes descargadas" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "%s imagenes saltadas" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "avisos" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "errores" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "Dispositivo de respaldo perdido" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "No se detectó un dispositivo de respaldo." + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "El dispositivo no tiene imágenes para descargar." + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "La descarga empezó desde %s" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "Imagen saltada" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "Imagen sobreescrita" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "La imagen ya existe" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "La magen no tiene miniatura" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "%(number)s de %(total)s imágenes copiadas" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "Descarga completa desde %s" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "Dispositivo" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "Tamaño" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "Progreso de descarga" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "Miniatura no puede mostrarse" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "Puede estar corrupta" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "Algunas preferencias serán restablecidas." + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" +"Una versión mas nueva de este programa fue ejecutada antes en este equipo.\n" +"\n" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" +"Las preferencias del programa parecen ser válidas, pero por favor revise a " +"fin de garantizar el correcto funcionamiento." + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "Lo siento, algunas preferencias son invalidas y serán restablecidas" + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "Aviso:" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" +"Esta versión del programa es más reciente que la versión previamente " +"ejecutada. Compruebe las preferencias." + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "Las preferencias fueron modificadas." + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" +"Esta versión del programa utiliza preferencias de la antigua versión. Sus " +"preferencias han sido actualizadas.\n" +"\n" +"Por favor, compruebe el correcto funcionamiento." + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "Ninguna preferencia necesita ser cambiada." + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" +"Esta versión del programa utiliza preferencias de la antigua versión. " +"Algunas de sus preferencias anteriores no eran válidas, y no pueden ser " +"actualizadas, por lo que serán restablecidas." + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "Problema usando pynotify." + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "Fallo al recibir capacidades del servidor pynotify" + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "y" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "Usando dispositivo de copia de seguridad" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "Usando dispositivo de copia de seguridad" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "Dispositivos de copia de seguridad no detectados" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "Detectado %(device)s con ruta %(path)s" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "Iniciar automaticamente la descarga está activa" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "Iniciar automaticamente la descarga está desactivada" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "Usando manualmente la ruta especifica" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "Todas las descargas completadas" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "MB/s" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "Aproximadamente 1 segundo restante" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "Aproximadamente %i segundos restantes" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "Aproximadamente 1 minuto restante" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Resta cerca de %(minutes)i:%(seconds)02i minutos" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "imagenes descargadas" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "Imágenes saltadas" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "_Descargar " + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "_Pausar" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "Las preferencias fueron cambiadas." + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "Adiós" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" +"mostrar la información del programa en la línea de comandos de como se " +"ejecuta el programa (por defecto: %default)" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "solo errores de salida en la línea de comando" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "" +"lista de extensiones de archivo de imagen que el programa reconoce y salir" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "y %s" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "Usando" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "%s ya se está ejecutando" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "Fecha" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "Texto" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "Nombre de archivo" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "Metadatos" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "Secuencias" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "Fecha de la imagen" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "Hoy" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "Ayer" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "Nombre + extensión" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "Nombre" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "Extensión" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "Número de imagen" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "Apertura" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "ISO" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "Tiempo de exposición" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "Longitud focal" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "Marca cámara" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "Modelo de la camara" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "Modelo corto de cámara" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "Modelo de cámara con guión corto" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "Número de serie" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "Obturador contador" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "Nombre propietario" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "Descargas de hoy" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "Número de sesión" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "Número de subcarpeta" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "Número almacenado" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "Letra de secuencia" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "Todos los digitos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "Último dígito" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "Últimos 2 dígitos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "Últimos 3 dígitos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "Últimos 4 dígitos" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "Mantener original" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "MAYÚSCULAS" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "minúsculas" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "Un dígito" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "Dos dígitos" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "Tres dígitos" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "Cuatro dígitos" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "Cinco dígitos" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "Seis dígitos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "Sub-segundos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "AAAAMMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "AAAA-MM-DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "AAMMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "AA-MM-DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "MMDDAAAA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "MMDDAA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "MMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "DDMMAAAA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "DDMMAA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "AAAA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "AA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "MM" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "HHMMSS" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "HHMM" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" +"Clave preferida '%(key)s' es inválida.\n" +"Esperado uno de %(value)s" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "Valor '%(value)s' es inválido" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "Estas preferencias no están bien formadas:" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "Metadato de sub-segundos no esta presente en la imagen" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "metadato %s no está presente en la imagen" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "Error en el campo de fecha. El valor %s parece inválido" + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "" +"La extensión fue especificada, pero el nombre de la imagen no tiene extensión" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "" +"Número de imagen fue especificado, pero el nombre de la imagen no lo tiene" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "Error generando nombre con componente %s" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Preferencias de subcarpeta no debería empezar con una %s" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Preferencias de subcarpeta no debería terminar con una %s" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" +"Preferencias de subcarpeta no debería contener dos %s uno después que el otro" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr " hh:mm" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr ":" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "<b>Respaldo</b>" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "<b>Compatibilidad con otros Sistemas Operativos</b>" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "<b>Carpeta de descargas</b>" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "<b>Subcarpeta de descargas</b>" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "<b>Ejemplo</b>" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "<b>Dispositivos de imagen</b>" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "<b>Conflictos en nombre de imagen</b>" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "<b>Renombrar imagen</b>" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "<b>Dispositivo de respaldo perdido</b>" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "<b>Automatización de programa</b>" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "<b>Número de secuencias</b>" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "<i>/media/externaldrive/Imágenes</i>" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "<i>Ejemplo: /home/user/photos</i>" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "<i>Ejemplo:</i>" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "<i>Nuevo:</i>" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "<i>Original:</i>" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Automatización</span>" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Respaldo</span>\t" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Carpeta de descargas</span>" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Manejo de errores</span>" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Dispositivos de imagen</span>" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Renombrar imagen</span>\t" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Opciones de renombre</span>" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "Agregar identificador único" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "Detectar automáticamente dispositivos de almacenamiento portables" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "Detectar automáticamente dispositivos de respaldo" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "Detectar automáticamente dispositivos de imagen" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "Automatización" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "Respaldo" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "Nombre de carpeta de respaldo" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "Ruta de respaldo:" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "Respaldar fotos al descargarlas" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" +"Seleccione una carpeta de descargas. Las subcarpetas para descargar fotos " +"serán creadas automáticamente en la carpeta usando la estructura " +"especificada abajo." + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" +"Seleccione si desea saltar la descarga de la imagen, o añadir un " +"identificador único." + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "Copyright © Damon Lynch 2007-09" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "Día de inicio:" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "Descargar / Pausar" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "Carpeta de descarga" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "Carpeta de descarga:" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "Descargas de hoy:" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "Manejo de errores" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "Registro de error" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "Salir del programa al completar exitosamente la descarga" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" +"Si desactiva la detección automática, seleccione la ruta exacta de respaldo." + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" +"Si desactiva la detección automática, seleccione la ruta exacta de las " +"imágenes." + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" +"Si activa la detección automática de Dispositivos de almacenamiento " +"portátil, será revisado completamente en busca de imágenes. En dispositivos " +"grandes, esto puede tomar algún tiempo." + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "Ignorar" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "Dispositivos de imagen" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "Renombrar imagen" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" +"Los dispositivos de imagen son aquellos desde los cuales descargará las " +"fotos, como cámaras, tarjetas de memoria o Dispositivos de almacenamiento " +"portátil.\n" +"\n" +"Puede descargar fotos desde múltiples dispositivos simultaneamente.\n" +"\n" +"<i>Si la descarga desde su cámara funciona lento o no funciona, pruebe " +"configurarla en modo PTP. Si esto no es posible, considere usar un lector de " +"tarjetas.</i>" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "Ruta de imagen:" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "Importar sus imágenes de manera eficiente y fiable" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "Sobreescribir" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "Preferencias: Rapid Photo Downloader" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" +"Rapid Photo Downloader es software libre; puede redistribuirlo y/o " +"modificarlo bajo los términos de la Licencia Pública General de GNU tal como " +"la publica la Free Software Foundation; tanto en la versión 2 de la Licencia " +"como (a su elección) cualquier versión posterior.\n" +"\n" +"Rapid Photo Downloader se distribuye con la esperanza de que será útil,pero " +"SIN NINGUNA GARANTÍA; sin incluso la garantía implicada de MERCANTIBILIDAD o " +"ADECUACIÓN PARA UN PROPÓSITO PARTICULAR. Vea la Licencia Pública General de " +"GNU para más detalles.\n" +"\n" +"Debería haber recibido una copia de la Licencia pública General de GNU junto " +"con Rapid Photo Downloader; si no, escriba a la Free Software Foundation, " +"Inc,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, EE. UU." + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "Opciones de renombre" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "Reportar un aviso" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "Reportar un error" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "Saltar" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "Saltar descarga" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" +"Especificar la carpeta en la que las copias de seguridad se almacenan en el " +"dispositivo. \n" +"\n" +"<i>Nota: esto también se utilizará para determinar si el dispositivo se " +"utiliza para las copias de seguridad. Para cada dispositivo que desea " +"utilizar para hacer copias de seguridad se creará una carpeta con este " +"nombre.</i>" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" +"Especifique la hora en formato de 24 horas en la que el numero de secuencia " +"de las <i> Descargas de hoy </i>, debe ser restablecido." + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" +"Especificar qué hacer cuando una imagen del mismo nombre ya se ha descargado " +"o respaldado." + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "Especificar que hacer cuando no hay dispositivos de respaldo." + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" +"Especificar si la imagen y los nombres de las carpetas se le han removido " +"carácteres que no se permite a otros sistemas operativos." + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "Empezar descargas al iniciar el programa" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "Empezar a descargar sobre dispositivo de imagen insertado" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "Número almacenado:" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "Quitar carácteres incompatibles" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "" +"Desmontar (\"expulsar\") el dispositivo de imagenes una vez completada la " +"descarga" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" +"Cuando respalde, elegir si desea sobreescribir la imagen en el dispositivo " +"de seguridad que tiene el mismo nombre, o de saltar su respaldo." + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" +"Puede tener respaldos de sus fotos en múltiples locaciones, por ejemplo: " +"discos duros externos." + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "_Limpiar descargas completadas" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "_Registro de errores" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "_Conseguir ayuda online" + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "_Ayuda" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "_Hacer una donación" + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "_Fotos" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "_Informar de un problema" + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "_Miniaturas" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "_Traducir esta aplicación" + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "_Ver" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "traductores por favor ignoren esto" + +#~ msgid "" +#~ "There is an error in the program preferences.\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "Hay un error en las preferencias del programa.\n" +#~ "Por favor, compruebe las preferencias, reinicie el programa y pruebe de " +#~ "nuevo." + +#~ msgid "" +#~ "Image devices are devices from which to download photos, such as memory " +#~ "cards or Portable Storage Devices.\n" +#~ "\n" +#~ "You can download photos from multiple image devices simultaneously." +#~ msgstr "" +#~ "Dispositivos de imagen a partir de los cuales descargará fotos, tales como " +#~ "tarjetas de memoria o dispositivos de almacenamiento portátil.\n" +#~ "\n" +#~ "Puede descargar fotos de múltiples dispositivos de imagen." + +#~ msgid "Resequence" +#~ msgstr "Resecuencia" + +#~ msgid "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>" +#~ msgstr "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>" + +#~ msgid "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>" +#~ msgstr "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>" + +#~ msgid "gtk-help" +#~ msgstr "Ayuda" diff --git a/po/fi.po b/po/fi.po new file mode 100644 index 0000000..d61697d --- /dev/null +++ b/po/fi.po @@ -0,0 +1,1369 @@ +# Finnish translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: 2009-06-01 18:21+0000\n" +"Last-Translator: Mikko Ruohola <polarfox@polarfox.net>\n" +"Language-Team: Finnish <fi@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-06-02 06:24+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "Nopea kuvien lataus" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "Virheelliset lataukset tänään\n" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "Palautetaan arvo nollaan.\n" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "'Päivän alku' asetuksen arvo on virheellinen\n" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "Palautuu keskiyöhön.\n" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "Virhe kuvan nimeämisasetuksissa" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "Anteeksi, näissä asetuksissa on virhe:\n" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "Palautetaan oletusarvot." + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "Virhe Latauskansion asetuksissa" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "Valitse kansio johon kuvan ladataan" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "Valitse kuvakansio" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "Valitse kansio johon tehdään varmuuskopio" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Varoitus:</b> Kuvan metatiedoista puuttuu tietoja tiedostonimen " +"luontiin. Ole hyvä ja käytä muita nimeämis asetuksia.</i>" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Varoitus:</b> Kuvan metatiedoista puuttuu tietoja kansiorakenteen " +"luontiin. Ole hyvä ja käytä muita kansionnimeämis asetuksia.</i>" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Esimerkki: %s</i>" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "Alikansioasetuksista poistettiin tarpeettomia arvoja." + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" +"Alikansioasetuksien asetukset ovat virheelliset, eikä niitä voida käyttää.\n" +"Ne palautetaan oletusasetuksiin." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "ulkoinenasema1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "ulkoinenasema2" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "etsii..." + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "Ohjelman setuksissa on virhe." + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" +"\n" +"Ole hyvä ja tarkista asetukset, käynnistä ohjelma uudelleen ja koita " +"uudestaan." + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "Latausta ei voida jatkaa" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "0 kuvaa %s kuvasta kopioitu" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" +"Laite etsintä on valmis: löytyi %(number)s kuvaa %(device)s laitteesta" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "Laite etsintä on valmis: kuvia ei löytynyt sijainnista %s" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "Kuvan tiedostonimeä ei pystytty luomaan" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" +"Lähde: %(source)s\n" +"Ongelma: %(problem)s" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Kuvan tiedostonimeä ei pystytty luomaan oikein. Tarkista että kuvassa on " +"riittävästi metatietoja." + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" +"Lähde: %(source)s\n" +"Kohde: %(destination)s\n" +"Ongelma: %(problem)s" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "Kuvaa ei voitu avata" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "Lähde: %s" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "Kuvassa ei ole metatietoja" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" +"Metatieto on välttämätöntä kansiorakenteen ja tiedostonimien luontiin.\n" +"Lähde: %s" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Kansiorakennetta ei voitu luoda. Tarkista että kuvassa on riittävästi " +"metatietoja." + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" +"Alikansio: %(subfolder)s\n" +"Kuva: %(image)s\n" +"Ongelma: %(problem)s" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Lähde: %(source)s\n" +"Kohde: %(destination)s" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "Yksilöinti '%s' lisätty" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "Uusi päivä on alkanut - Palautetaan 'Latauksia Tänään' luku" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "Kopiointivirhe" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" +"Lähde: %(source)s\n" +"Kohde: %(destination)s\n" +"Virhe: %(errorno)s %(strerror)s" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "Kuvaa ei kopioitu." + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "Kuvan varmuuskopio on jo olemassa" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "Varmuuskopiointi virhe" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Kohdekansiota ei voitu luoda\n" +"%(directory)s\n" +"Virhe: %(errno)s %(strerror)s" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Lähde: %(source)s\n" +"Kohde: %(destination)s\n" +"Virhe: %(errno)s %(strerror)s" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "Laite voidaan turvallisesti poistaa" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "%s kuvaa ladattu" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "%s kuvaa ohitettu" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "varoitukset" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "virheet" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "Varmuuskopiolaite puuttuu" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "Varmuuskopiolaitetta ei löytynyt" + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "Laitteessa ei ole kuvia ladattavaksi." + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "Lataus lähteestä %s on alkanut" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "Kuva ohitettu" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "Kuva korvattu" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "Kuva on jo olemassa" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "Kuvalla ei ole näytekuvaa" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "%(number)s kuvaa %(total)s kuvasta kopioitu" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "Lataus lähteestä %s valmis" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "Laite" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "Koko" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "Latauksen edistyminen" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "Näytekuvaa ei voida näyttää" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "Se voi olla vahingoittunut" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "Jotkin asetukset palautetaan." + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" +"Ohjelman uudempaa versiota on käytetty tässä tietokoneessa.\n" +"\n" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" +"Ohjelma on kelpaava, mutta ole hyvä ja tarkista että ohjelma toimii oikein." + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "" +"Anteeksi, jotkin asetukset ovat virheellisiä ja ne palautetaan " +"oletusarvoihin." + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "Varoitus:" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" +"Tämä ohjelma on uudempi kuin aikaisemmin käytetty. Tarkista asetukset." + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "Asetuksia on muokattu." + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" +"Tämä ohjelmaversio käyttää eri asetuksia kuin vanha versio. Asetuksesi on " +"päivitettu.\n" +"\n" +"Ole hyvä ja tarkista ne varmistaaksesi ohjelman toiminta." + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "Asetuksia ei tarvinnut muuttaa." + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" +"Tämä ohjelmaversio käyttää eri asetuksia kuin vanha versio. Jotkin entisistä " +"asetuksistasi olivat virheellisiä ja niitä ei voitu päivittää. Ne " +"palautetaan oletuksiin." + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "Ongelmia pynotifyn käytössä." + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "Ei saanut pynotify-palvelimen ominaisuuksia." + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "ja" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "Käyttää varmuuskopiolaitteita" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "Käyttää varmuuskopiolaitetta" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "Varmuuskopiolaitetta ei löytynyt" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "Löytyi %(device)s laitetta polusta %(path)s" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "Automaattinen latauksen aloitus on päällä" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "Automaattinen latauksen aloitus on pois päältä" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "Käytetään käsin valittua polkua" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "Kaikki lataukset valmiita" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "Mt/s" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "Noin 1 sekunti jäljellä" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "Noin %i sekuntia jäljellä" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "Noin 1 minuutti jäljellä" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Noin %(minutes)i:%(seconds)02i minuuttia jäljellä" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "kuvia ladattu" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "kuvia ohitettu" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "_Lataa " + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "_Keskeytä" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "Asetuksia muutettiin." + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "Näkemiin" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" +"näytä ohjelman tiedot komentorivillä kun ohjelma käynnistetään (oletus: " +"%default)" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "tulosta vain virheet komentoriville" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "Listaa kuvatiedostopäätteet jotka ohjelma tunnistaa ja poistu" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "ja %s" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "Käyttäen" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "%s on jo käynnissä" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "Ajankohta" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "Teksti" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "Tiedostonimi" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "Metatieto" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "Numeroinnit" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "Kuvan päivämäärä" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "Tänään" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "Huomenna" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "Nimi + pääte" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "Nimi" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "Tiedostopääte" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "Kuvan numero" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "Aukko" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "Herkkyys" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "Valotusaika" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "Polttoväli" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "Kameran merkki" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "Kameran malli" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "Lyhyt kameramalli" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "Tavutettu lyhyt kameran malli" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "Sarjanumero" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "Suljinlaskuri" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "Omistajan nimi" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "Latauksia tänään" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "Istuntonumero" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "Alikansion numero" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "Tallennettu numero" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "Kirjainsarja" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "Kaikki numerot" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "Viimeinen numero" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "Kaksi viimeistä numeroa" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "Kolme viimeistä numeroa" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "Neljä viimeistä numeroa" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "Alkuperäinen kirjoitusasu" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "ISOT KIRJAIMET" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "pienet kirjaimet" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "Yksi numero" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "Kaksi numeroa" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "Kolme numeroa" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "Neljä numeroa" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "Viisi numeroa" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "Kuusi numeroa" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "sekunnin osat" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "VVVVKKPP" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "VVVV-KK-PP" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "VVKKPP" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "VV-KK-PP" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "KKPPVVVV" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "KKPPVV" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "KKPP" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "PPKKVVVV" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "PPKKVV" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "VVVV" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "VV" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "KK" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "PP" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "hhmmss" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "hhmm" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" +"Asetus '%(key)s' on virheellinen.\n" +"Tulisi olla yksi näistä %(value)s" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "Asetuksen arvo '%(value)s' on virheellinen" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "Nämä asetukset eivät ole oikeassa muodossa:" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "sekunnin osia ei löydy metatiedoista tässä kuvassa" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "%s metatietoa ei löydy tästä kuvasta" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "Virhe aikamäärityksessä. Arvo %s näyttää virheelliseltä" + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "" +"tiedostopääte oli määritelty mutta kuvan nimessä ei ole tiedostopäätettä" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "kuvan numero oli määritelty, mutta tiedostonimessä ei ole numeroa" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "virhe luotaessa nimeä osalla %s" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Alikansioiiden asetusten ei tulisi alkaa %s" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Alikansioiden asetusten ei tulisi loppua %s" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "Alikansioiden asetusten ei tulisi sisältää kahta vierekkäistä %s" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr " hh:mm" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr ":" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "<b>Varmuuskopio</b>" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "<b>Yhteensopivuus käyttöjärjestelmien kanssa</b>" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "<b>Latauskansio</b>" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "<b>Latausalikansio</b>" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "<b>Esimerkki</b>" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "<b>Kuva laitteet</b>" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "<b>Kuvannimien konfliktit</b>" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "<b>Kuvan uudelleennimeäminen</b>" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "<b>Puuttuvat varmusskopiolaitteet</b>" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "<b>Ohjelman automatiikka</b>" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "<b>Numerointi</b>" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "<i>/media/ulkoinenlevy/Kuvat</i>" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "<i>Esimerkki: /home/käyttäjä/kuvat</i>" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "<i>Esimerkki</i>" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "<i>Uusi:</i>" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "<i>Alkuperäinen:</i>" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Automatisointi</span>" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Varmuuskopio</span>\t" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Latauskansio</span>" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Virheenkäsittely</span>" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Kuvalaitteet</span>" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Kuvan uudelleennimeäminen</span>\t" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Uudelleennimeämis valinnat</span>" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "Lisää yksilöllinen tunniste" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "Tunnista automaattisesti ulkoiset tallennuslaitteet" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "Tunnista automaattisesti varmuuskopiolaitteet" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "Tunnista automaattisesti kuvalaitteet" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "Automatisointi" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "Varmuuskopio" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "Varmuuskopiokansion nimi:" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "Varmuuskopioiden sijainti:" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "Tee varmuuskopio ladattaessa kuvia" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" +"Valitse latauskansio. Alikansiot ladatuille kuville tehdään automaattisesti " +"tähän kansioon käyttäen alla määriteltyä rakennetta käyttäen." + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" +"Valitse ohitetaanko kuva ladattaessa vai lisätäänkö nimeen yksilöllinen " +"tunniste." + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "Tekijänoikeus Damon Lynch 2007-09" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "Päivän alku:" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "Lataa / Keskeytä" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "Latauskansio" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "Latauskansio:" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "Latauksia tänään:" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "Virheenkäsittely" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "Virheloki" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "Poistu ohjelmasta onnistuneen latauksen jälkeen" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" +"Jos poistat automaattisen tunnistuksen käytöstä, määritä varmuuskopioiden " +"tarkka sijainti." + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" +"Jos poistat automaattisen tunnistuksen käytöstä, määritä tarkka kuvien " +"sijainti." + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" +"Jos kytket päälle automaattisen kannettavan laitteen tunnistuksen, koko " +"laite käydään läpi kuvia etsittäessä, tämä voi kestää hetken." + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "Ohita" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "Kuvalaitteet" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "Kuvan uudelleennimeäminen" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" +"Kuvalaitteet ovat laitteita joista kuvat ladataan, kuten kameroita, " +"muistikortteja tai muita kannettavia laitteita.\n" +"\n" +"Voit ladata valokuvia monesta kuvalaitteesta yhtäaikaa.\n" +"\n" +"<i>Jos lataus suoraan kamerasta toimii huonosti tai ei ollenkaan, koita " +"asettaa se PTP tilaan. Jos ei ole mahdollista, harkitse kortinlukijan " +"käyttämistä.</i>" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "Kuvan sijainti:" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "Tuo kuvasti tehokkaasti ja turvallisesti" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "Ylikirjoita" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "Asetukset: Nopea Valokuvien Lataaja" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "Uudelleennimeämis valinnat" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "Raportoi varoitus" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "Raportoi virhe" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "Ohita" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "Ohita lataus" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" +"Määritä kansio johon varmuuskopiot tallennetaan laitteessa. \n" +"\n" +"<i>Huomaa: tämä määrittää myös käytetäänkö laitetta varmuuskopiointiin vai " +"ei. Jokaiseen varmuuskopiolaitteeseen tulee tehdä tämän niminen " +"hakemisto.</i>" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" +"Valitse aika 24 tunnin muodossa jossa <i>Latauksia tänään</i> numerointi " +"tulisi palauttaa." + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" +"Valitse mitä tehdään kun samanniminen kuva on jo ladattu tai varmuuskopioitu." + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "Valitse mitä tehdään jos varmuuskopiolaitteita ei löydy." + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" +"Valitse tuleeko kuva ja hakemistonimistä poistaa merkit joita ei tueta " +"toisissa käyttöjärjestelmissä." + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "Aloita lataus kun ohjelma käynnistetään" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "Aloita lataus kun kuvalaite kytketään" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "Tallennettu numero:" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "Poista yhteensopimattomat merkit" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "Poista kuvalaite kun lataus on valmis" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" +"Varmuuskopioitaessa, valitse ylikirjoitetaanko kuva varmuuskopiolaitteessa " +"jos saman niminen kuva on jo olemassa, vai ohitetaanko se." + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" +"Voit varmuuskopioida kuvasi useaan kohteeseen kun kuvia ladataan, esim. " +"ulkoisille kovalevyille." + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "_Tyhjennä valmistuneet lataukset" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "Virheloki" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "_Hae ohjeita netistä..." + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "_Ohje" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "_Tee lahjoitus" + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "_Valokuvat" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "_Raportoi ongelma..." + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "_Näytekuvat" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "_Käännä tämä ohjelma..." + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "_Näytä" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "kääntäjät, olkaa hyvä ja olkaa välittämättä tästä" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..99a33f1 --- /dev/null +++ b/po/it.po @@ -0,0 +1,1407 @@ +# Italian translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: 2009-05-30 08:13+0000\n" +"Last-Translator: Marco Solari <marcosolari@gmail.com>\n" +"Language-Team: Italian <it@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-05-30 09:36+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "Rapid Photo Downloader" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "Il valore Downloads Oggi non è valido.\n" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "Resetta i valori a zero.\n" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "Il valore della preferenza 'Inizio del giorno' è corrotto.\n" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "Si resetta a mezzanotte.\n" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "Errore nelle preferenze Rinomina Immagine" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "Scusa ma queste preferenze contengono un errore:\n" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "Si resettano ai valori di default." + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "Errore nelle preferenze Sottocartella di Download" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "Scegliere la cartella in cui scaricare le foto" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "Selezionare una cartella contenente le foto" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "Selezionare una cartella per le immagini di backup" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Attenzione:</b> Non ci sono metadati sufficienti per generare " +"interamente il nome. Usa diverse opzioni di rinomina.</i>" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Attenzione:</b> Non ci sono metadati sufficienti per generare " +"interamente le sottocartelle. Usa diverse opzioni di nomina delle " +"sottocartelle.</i>" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Esempio: %s</i>" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "" +"Sono stati rimossi alcuni valori non necessari nelle preferenze " +"sottocartella." + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" +"Le preferenze sottocartella inserite non sono valide e non possono essere " +"usate.\n" +"Saranno reimpostate ai loro valori di default." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "driveesterno1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "driveesterno1" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "scansione in corso..." + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "C'è un errore nelle referenze programma." + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" +"\n" +"Per favore controlla le preferenze, riavvia il programma e prova di nuovo" + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "Il download non può procedere" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "0 di %s immagini copiate" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" +"Scansione del dispositivo completata: trovate %(number)s immagini in " +"%(device)s" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "Scansione del dispositivo completata: nessuna immagine trovata in %s" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "Non si è potuto generare il nome file dell'immagine" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" +"Origine: %(source)s\n" +"Problema: %(problem)s" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Non si è potuto generare correttamente il nome file dell'immagine. " +"Controllare che ci siano sufficienti metadati per l'immagine." + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" +"Origine: %(source)s\n" +"Destinazione: %(destination)s\n" +"Problema: %(problem)s" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "Impossibile aprire l'immagine" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "Origine: %s" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "L'immagine non ha metadati" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" +"I metadati sono essenziali per generare i nomi delle sottocartelle / " +"immagini.\n" +"Origine: %s" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Impossibile generare correttamente il nome della sottocartella. Controllare " +"che ci siano metadati sufficienti per l'immagine." + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" +"Sottocartella: %(subfolder)s\n" +"Immagine: %(image)s\n" +"Problema: %(problem)s" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Origine: %(source)s\n" +"Destinazione: %(destination)s" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "Aggiunto identificatore univoco '%s'" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" +"Un nuovo giorno è iniziato - si resetta il numero di sequenza 'Downloads " +"Oggi'" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "Errore nella copia del download" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" +"Origine: %(source)s\n" +"Destinazione: %(destination)s\n" +"Errore: %(errorno)s %(strerror)s" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "L'immagine non è stata copiata." + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "L'immagine di backup esiste già" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "Errore durante il backup" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Non si è potuto creare la cartella di destinazione\n" +"%(directory)s\n" +"Errore: %(errno)s %(strerror)s" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Origine: %(source)s\n" +"Destinazione: %(destination)s\n" +"Errore: %(errno)s %(strerror)s" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "Il dispositivo può adesso essere rimosso in modo sicuro" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "%s immagini scaricate" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "%s immagini ignorate" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "avvertenze" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "errori" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "Manca il dispositivo di backup" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "Nessun dispositivo di backup è stato rilevato." + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "Questo dispositivo non ha immagini da scaricare." + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "Il download è inziato da %s" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "Immagine ignorata" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "Immagine sovrascritta" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "L'immagine esiste già" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "L'immagine non ha miniatura" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "%(number)s di %(total)s immagini copiate" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "Download completato da %s" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "Dispositivo" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "Dimensione" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "Avanzamento del download" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "La miniatura non può essere visualizzata" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "Può essere corrotto" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "Alcune preferenze saranno azzerate." + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" +"Una versione più recente di questo programma è stato eseguito su questo " +"computer.\n" +"\n" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" +"Le preferenze del programma sembrano essere valide, ma occorre controllarle " +"per assicurare la correttezza delle operazioni." + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "Spiacente, alcune preferenze non sono valide e saranno ripristinate." + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "Attenzione:" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" +"Questa versione del programma è più recente della versione eseguita in " +"precedenza. Si controllano le preferenze." + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "Le preferenze sono state modificate." + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" +"Questa versione del programma utilizza preferenze diverse dalla vecchia " +"versione. Le tue preferenze sono state aggiornate.\n" +"\n" +"Controllarle per assicurare la correttezza delle operazioni." + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "Non occorre cambiare alcuna preferenza." + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" +"Questa versione del programma utilizza preferenze diverse dalla vecchia " +"versione. Alcune delle preferenze precedenti non erano valide, e non hanno " +"potuto essere aggiornate. Saranno reimpostate." + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "Riscontrato un problema usando pynotify." + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "Impossibile acquisire le proprietà server di pynotify." + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "e" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "Si utilizzano dispositivi di backup" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "Si utilizza un dispositivo di backup" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "Non è stato rilevato nessun dispositivo di backup" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "Rilevato %(device)s con il percorso %(path)s" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "Avvio automatico dei download attivo" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "Avvio automatico dei download disattivo" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "Si utilizza un percorso specificato manualmente" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "Tutti i download completati" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "MB/s" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "Circa 1 secondo rimanente" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "Circa %i secondi rimanenti" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "Manca circa 1 minuto" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Circa %(minutes)i:%(seconds)02i minuti rimanenti" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "immagini scaricate" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "immagini saltate" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "_Download " + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "_Pausa" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "Le preferenze sono state modificate." + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "Arrivederci" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" +"visualizza informazioni sul programma sulla riga comando quando il programma " +"è in esecuzione (default: %default)" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "visualizza solo gli errori sulla riga comando" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "" +"elenca le estensioni per i files delle immagini che il programma riconosce, " +"ed esce" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "e %s" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "Si usa" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "%s è già in esecuzione" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "Data e ora" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "Testo" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "Nome file" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "Metadati" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "Ordinamenti" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "Data dell'immagine" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "Oggi" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "Ieri" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "Nome + estensione" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "Nome" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "Estensione" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "Numero immagine" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "Apertura" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "ISO" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "Tempo di esposizione" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "Lunghezza focale" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "Marca della fotocamera" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "Modello della fotocamera (es.: Canon EOS-1Ds Mark III)" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "Modello brevissimo della fotocamera (es.: D300)" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "Modello breve della fotocamera (es.: DSC-P92)" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "Numero seriale" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "Contatore dell'otturatore" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "Nome del proprietario" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "Downloads oggi" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "Numero della sessione" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "Numero della sottocartella" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "Numero memorizzato" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "Lettera di sequenza" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "Tutte le cifre" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "Ultima cifra" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "Ultime 2 cifre" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "Ultime 3 cifre" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "Ultime 4 cifre" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "Caso originale" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "MAIUSCOLO" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "minuscolo" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "Una cifra" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "Due cifre" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "Tre cifre" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "Quattro cifre" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "Cinque cifre" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "Sei cifre" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "Sotto-secondi" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "YYYYMMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "YYYY-MM-DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "YYMMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "YY-MM-DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "MMDDYYYY" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "MMDDYY" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "MMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "DDMMYYYY" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "DDMMYY" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "YYYY" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "YY" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "MM" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "HHMMSS" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "HHMM" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" +"La chiave delle preferenze '%(key)s' non è valida\n" +"Sono previsti uno di %(value)s" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "Il valore delle preferenze '%(value)s' non è valido" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "Queste preferenze non sono formalmente corrette:" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "Metadato sotto-secondi non presente nell'immagine" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "Metadato %s non presente nell'immagine" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "Errore nel componente data e ora. Il valore %s non sembra valido" + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "" +"è stata specificata un'estensione ma il nome dell'immagine non ha estensione" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "" +"è stato specificato un numero immagine ma il nome file dell'immagine non ha " +"numero" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "errore nella generazione del nme con il componente %s" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Le preferenze sottocartella non dovrebbero iniziare con un %s" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Le preferenze sottocartella non dovrebbero terminare con un %s" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" +"Le preferenze sottocartella non dovrebbero contenere due %s uno dopo l'altro" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr " hh:mm" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr ":" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "<b>Backup</b>" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "<b>Compatibilità con Altri Sistemi Operativi</b>" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "<b>Cartella di Download</b>" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "<b>Sottocartella di Download</b>" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "<b>Esempio</b>" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "<b>Dispositivi Immagine</b>" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "<b>Conflitti sul Nome Immagine</b>" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "<b>Rinomina Immagine</b>" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "<b>Dispositivi di Backup Mancanti</b>" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "<b>Automazione Programma</b>" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "<b>Numeri di Sequenza</b>" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "<i>/media/externaldrive/Photos</i>" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "<i>Esempio: /home/utente/fotografie</i>" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "<i>Esempio:</i>" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "<i>Nuovo:</i>" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "<i>Originale:</i>" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Automazione</span>" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Cartella di Download</span>" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Gestione Errori</span>" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Dispositivi Immagine</span>" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Rinomina Immagine</span>\t" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Opzioni di Rinomina</span>" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "Aggiunta di un identificatore univoco" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "Rileva automaticamente i Dispositivi di Memorizzazione Portatile" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "Rileva automaticamente i dispositivi di backup" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "Rileva automaticamente i dispositivi immagine" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "Automazione" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "Backup" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "Nome della cartella di backup:" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "Locazione del backup:" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "Backup delle foto durante il download" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" +"Scelta della cartella di download. Sottocartelle per le fotografie scaricate " +"saranno create automaticamente in questa cartella utilizzando la struttura " +"specificata sotto." + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" +"Scelta se saltare il download dell'immagine, oppure aggiungere un " +"identificatore univoco." + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "Copyright Damon Lynch 2007-09" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "Giorno iniziale:" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "Download / Pausa" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "Cartella di Download" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "Cartella di download:" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "Downloads oggi:" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "Gestione Errori" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "Registrazione degli Errori" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "" +"Termina il programma al termine del completamento di un download con esito " +"positivo" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" +"Se si disabilita il rilevamento automatico, scegliere l'esatta locazione del " +"backup." + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" +"Se si disabilita il rilevamento automatico, scegliere l'esatta locazione " +"delle immagini." + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" +"Se abiliti il riconoscimento automatico dei dispositivi di memorizzazione " +"portatile (PSD), tutto il dispositivo sarà sottoposto a scansione per le " +"immagini. Su dispositivi capienti ciò potrebbe richiedere tempo." + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "Ignora" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "Dispositivi Immagine" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "Rinomina Immagini" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" +"I dispositivi immaginw sono dispositivi da cui scaricare fotografie, come " +"macchine fotografiche, schede di memoria o dispositivi di memorizzazione " +"portatili (PSD).\n" +"\n" +"Puoi scaricare fotografie da più dispositivi immagine contemporaneamente.\n" +"\n" +"<i>Se il download diretto dalla tua macchina fotografica funziona male o non " +"funziona per niente, prova ad impostarla in modalità PTP. Se questo non " +"fosse possibile, considera di utilizzare un lettore di schede di memoria.</i>" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "Locazione dell'immagine" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "Importa le tue immagini in modo efficiente ed affidabile" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "Sovrascrivi" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "Preferenze: Rapid Photo Downloader" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" +"Rapid Photo Downloader è software libero; puoi ridistribuirlo e/o " +"modificarlo alle condizioni della GNU General Public License come pubblicato " +"dalla Free Software Foundation; o la versione 2 della Licenza, o (a tua " +"scelta) ogni versione successiva.\n" +" \n" +"Rapid Photo Downloader è distributed nella speranza che sarà utile, ma SENZA " +"NESSUNA GARANZIA; anche senza la garanzia implicita di COMMERCIABILITA' o " +"IDONEITA' PER UNO SCOPO PARTICOLARE. Vedi la GNU General Public License per " +"dettagli ulteriori.\n" +"\n" +"Dovresti aver ricevuto una copia della GNU General Public License con Rapid " +"Photo Downloader; altrimenti, scrivi alla Free Software Foundation, Inc., 51 " +"Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "Opzioni di Rinomina" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "Riporta una segnalazione" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "Riporta un errore" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "Salta" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "Salta il download" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" +"Specifica la cartella nella quale i backups sono memorizzati sul " +"dispositivo. \n" +"\n" +"<i>Nota: questa sarà anche usata per determinare se un dispositivo è " +"utilizzato per i backups o meno. Per ogni dispositivo che si vuol utilizzare " +"per il backup, crearvi una cartella con questo nome.</i>" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" +"Specificare l'ora nel formato 24 ore a cui il numero di sequenza " +"<i>Downloads oggi</i> dovrebbe essere reimpostato." + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" +"Specificare cosa fare quando un'immagine con lo stesso nome è già stata " +"scaricata o salvata." + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "Specificare cosa fare quando non ci sono dispositivi di backup." + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" +"Specificare se l'immagine o i nomi di cartella dovrebbero avere rimossi i " +"caratteri non permessi da altri sistemi operativi." + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "Inizia il download all'avvio del programma" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "Inizia il download all'inserimento di un dispositivo immagini" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "Numero memorizzato:" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "Elimina caratteri incompatibili" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "Smonta (\"espelle\") il dispositivo immagini al termine del download" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" +"Quando si effettua il backup, scegliere se sovrascrivere un'immagine che ha " +"lo stesso nome sul dispositivo di backup, o se saltarne il backup." + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" +"Si possono salvare in locazioni diverse le proprie fotografie mentre vengono " +"scaricate, ad esempio un dischi esterni." + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "_Svotare i Downloads Completati" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "_Registrazione Errori" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "_Richiedi Aiuto In Linea..." + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "_Aiuto" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "_Fai una Donazione..." + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "_Fotografie" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "_Segnala un Problema..." + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "_Miniature" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "_Traduci questa Applicazione..." + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "_Visualizzazione" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "si pregano i traduttori di ignorare questo" + +#~ msgid "Resequence" +#~ msgstr "Riordinamento" + +#~ msgid "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>" +#~ msgstr "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>\n" +#~ "Marco Solari <marcosolari@gmail.com>" + +#~ msgid "gtk-help" +#~ msgstr "Aiuto-gtk" diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..c228fc2 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,1426 @@ +# Polish translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: 2009-06-01 19:36+0000\n" +"Last-Translator: mmiicc <mpredotka@gmail.com>\n" +"Language-Team: Polish <pl@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-06-02 06:24+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "Rapid Photo Downloader" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "Nieprawidłowa wartość Pobierań dzisiaj.\n" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "Resetowanie wartości do zera.\n" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "Wartość preferencji \"Początek dnia\" jest uszkodzona.\n" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "Resetowanie do północy.\n" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "Błąd w preferencjach zmiany nazw obrazów" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "Przepraszamy, te preferencje zawierają błąd:\n" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "Resetowanie do wartości domyślnych." + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "Błąd w preferencjach podkatalogu pobierania" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "Wybór katalogu dla pobieranych zdjęć" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "Wybór katalogu obrazów" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "Wybór katalogu do utworzenia kopii zapasowej" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Ostrzeżenie:</b> Ilość metadanych jest niewystarczająca do pełnego " +"wygenerowania nazwy. Proszę użyć innej opcji zmiany nazwy.</i>" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Ostrzeżenie:</b> Ilość metadanych jest niewystarczająca do pełnego " +"wygenerowania podkatalogów. Proszę użyć innej opcji określenia nazwy " +"podkatalogu </i>" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Przykład: %s</i>" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "" +"Pewne niepotrzebne wartości zostały usunięte z preferencji podkatalogu." + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" +"Wprowadzone preferencje podkatalogu są nieprawidłowe i nie mogą zostać " +"użyte.\n" +"Zostaną przywrócone ich domyślne wartości." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "dyskzewnętrzny1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "dyskzewnętrzny2" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "wyszukiwanie..." + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "Błąd w preferencjach programu." + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" +"\n" +"Proszę sprawdzić preferencje, uruchomić program ponownie i spróbować jeszcze " +"raz." + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "Pobieranie nie może się odbyć" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "skopiowano 0 z %s obrazów" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" +"Wyszukiwanie zakończone: w katalogu %(device)s znaleziono obrazów %(number)s" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "Wyszukiwanie zakończone: nie znaleziono obrazów w katalogu %s" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "Nazwa pliku obrazu nie mogła zostać wygenerowana" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" +"Źródło: %(source)s\n" +"Problem: %(problem)s" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Nazwa pliku obrazu nie mogła zostać prawidłowo wygenerowana. Proszę " +"sprawdzić, czy metadane obrazu są wystarczające." + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" +"Źródło: %(source)s\n" +"Cel: %(destination)s\n" +"Problem: %(problem)s" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "Nie można otworzyć obrazu" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "Źródło: %s" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "Obraz nie posiada metadanych" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" +"Metadane są niezbędne aby wygenerować nazw podkatalogów / obrazów.\n" +"Źródło: %s" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Nazwa podkatalogu nie mogła zostać prawidłowo wygenerowana. Proszę " +"sprawdzić, czy metadane obrazu są wystarczające." + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" +"Podkatalog: %(subfolder)s\n" +"Obraz: %(image)s\n" +"Problem: %(problem)s" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Źródło: %(source)s\n" +"Cel: %(destination)s" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "Dodano unikatowy identyfikator \"%s\"" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" +"Rozpoczął się nowy dzień - resetowanie numeru sekwencji \"Pobierań dzisiaj\"" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "Błąd pobierania" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" +"Źródło: %(source)s\n" +"Cel: %(destination)s\n" +"Błąd: %(errorno)s %(strerror)s" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "Obraz nie został skopiowany." + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "Kopia zapasowa obrazu już istnieje" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "Błąd tworzenia kopii zapasowej" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Nie można utworzyć katalogu docelowego\n" +"%(directory)s\n" +"Błąd: %(errno)s %(strerror)s" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Źródło: %(source)s\n" +"Cel: %(destination)s\n" +"Błąd: %(errno)s %(strerror)s" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "Teraz można bezpiecznie usunąć urządzenie" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "obrazów pobranych: %s" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "obrazów pominiętych: %s" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "ostrzeżenia" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "błędy" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "Brak urządzenia do zapisu kopii zapasowej" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "Nie wykryto urządzenia na którym można utworzyć kopię zapasową" + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "Ten nośnik nie zawiera obrazów, które można pobrać." + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "Rozpoczęto pobieranie z %s" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "Obraz pominięto" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "Obraz nadpisano" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "Obraz już istnieje" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "Obraz nie posiada miniatury" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "Skopiowano %(number)s z %(total)s obrazów" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "Ukończono pobieranie z %s" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "Urządzenie" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "Rozmiar" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "Postęp pobierania" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "Nie można wyświetlić miniatury" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "Może być uszkodzone" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "Niektóre preferencje zostaną zresetowane." + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" +"Nowsza wersja tego programu była poprzednio uruchomiona na tym komputerze.\n" +"\n" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" +"Preferencje programu wydają się być właściwe, proszę jednak sprawdzić, czy " +"zapewniają prawidłowe działanie." + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "" +"Przepraszamy, niektóre preferencje są nieprawidłowe i zostaną zresetowane." + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "Ostrzeżenie:" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" +"Ta wersja programu jest nowsza od uruchomionej poprzednio. Sprawdzanie " +"preferencji." + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "Preferencje zostały zmodyfikowane." + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" +"Ta wersja programu używa innych preferencji niż starsza wersja. Preferencje " +"zostały zaktualizowane.\n" +"\n" +"Proszę je sprawdzić, czy zapewniają prawidłowe działanie." + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "Żadne preferencje nie muszą zostać zmienione." + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" +"Ta wersja programu używa innych preferencji niż starsza wersja. Niektóre z " +"poprzednich preferencji były nieprawidłowe i nie mogły zostać " +"zaktualizowane. Zostaną one zresetowane." + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "Problem z użyciem pynotify." + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "Pobranie właściwości serwera pynotify nieudane." + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "oraz" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "Użycie urządzeń do zapisu kopii zapasowej" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "Użycie urządzenia do zapisu kopii zapasowej" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "Nie wykryto urządzeń na których można utworzyć kopię zapasową" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "Wykryto %(device)s ze ścieżką %(path)s" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "Automatyczne rozpoczęcie pobierania jest włączone" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "Automatyczne rozpoczęcie pobierania jest wyłączone" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "Użycie ręcznie wprowadzonej ścieżki" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "Ukończono wszystkie pobierania" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "MB/s" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "Pozostała około sekunda" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "Pozostało około %i sekund" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "Pozostała około minuta" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Pozostało około %(minutes)i:%(seconds)02i minut" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "obrazów pobranych" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "obrazów pominiętych" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "_Pobierz " + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "W_strzymaj" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "Preferencje zostały zmienione." + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "Do zobaczenia" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" +"wyświetl informacje programu w linii komend podczas działania programu " +"(domyślnie: %default)" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "wyświetlaj jedynie błędy w linii komend" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "wypisz typy plików rozpoznawane przez program i zakończ" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "oraz %s" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "Użycie" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "%s jest już uruchomiony" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "Data czas" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "Tekst" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "Nazwa pliku" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "Metadane" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "Sekwencje" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "Data zdjęcia" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "Dzisiaj" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "Wczoraj" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "Nazwa + rozszerzenie" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "Nazwa" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "Rozszerzenie" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "Numer obrazu" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "Przysłona" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "ISO" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "Czas naświetlania" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "Ogniskowa" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "Producent aparatu" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "Model aparatu" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "Skrót modelu aparatu" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "Skrót z myślnikiem modelu aparatu" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "Numer seryjny" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "Licznik migawki" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "Nazwa właściciela" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "Pobierań dzisiaj" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "Numer sesji" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "Numer podkatalogu" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "Numer zachowany" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "Litera sekwencji" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "Wszystkie cyfry" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "Ostatnia cyfra" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "Ostatnie 2 cyfry" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "Ostatnie 3 cyfry" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "Ostatnie 4 cyfry" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "Oryginalna wielkość liter" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "WIELKIE LITERY" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "małe litery" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "Jedna cyfra" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "Dwie cyfry" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "Trzy cyfry" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "Cztery cyfry" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "Pięć cyfr" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "Sześć cyfr" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "Części sekundy" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "RRRRMMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "RRRR-MM-DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "RRMMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "RR-MM-DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "MMDDRRRR" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "MMDDRR" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "MMDD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "DDMMRRRR" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "DDMMRR" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "RRRR" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "RR" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "MM" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "GGMMSS" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "GGMM" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" +"Klucz preferencji \"%(key)s\" jest nieprawidłowy.\n" +"Oczekiwano %(value)s" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "Wartość preferencji \"%(value)s\" jest nieprawidłowa" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "Następujące preferencje nie są dobrze sformułowane:" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "Obraz nie zawiera metadanych części sekundy" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "Obraz nie zawiera metadanych %s" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "Błąd w składniku data czas. Nieprawidłowa wartość %s" + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "" +"rozszerzenie zostało określone ale obraz nie posiada żadnego rozszerzenia" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "" +"numer obrazu został określony ale nazwa pliku nie posiada żadnego numeru" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "błąd przy tworzeniu nazwy ze składową %s" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Preferencje podkatalogu nie powinny zaczynać się od %s" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Preferencje podkatalogu nie powinny kończyć się na %s" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" +"Preferencje podkatalogu nie powinny zawierać dwóch %s jeden po drugim" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr " gg:mm" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr ":" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "<b>Kopia zapasowa</b>" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "<b>Zgodność z innymi systemami operacyjnymi</b>" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "<b>Katalog pobierania</b>" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "<b>Podkatalogi pobierania</b>" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "<b>Przykład</b>" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "<b>Nośniki obrazów</b>" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "<b>Konflikty nazw obrazów</b>" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "<b>Zmiana nazw obrazów</b>" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "<b>Brak urządzeń do zapisu kopii zapasowej</b>" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "<b>Automatyzacja programu</b>" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "<b>Numery sekwencji</b>" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "<i>/media/dyskzewnętrzny/Photos</i>" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "<i>Przykład: /home/user/photos</i>" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "<i>Przykład:</i>" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "<i>Nowa:</i>" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "<i>Oryginalna:</i>" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Automatyzacja</span>" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Kopia zapasowa</span>\t" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Katalog pobierania</span>" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Obsługa błędów</span>" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Nośniki obrazów</span>" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "<span weight=\"bold\" size=\"x-large\">Zmiana nazw obrazów</span>\t" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Opcje zmiany nazw</span>" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "Dodaj unikatowy identyfikator" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "Automatycznie wykryj przenośne magazyny danych" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "" +"Automatycznie wykryj urządzenia na których można utworzyć kopię zapasową" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "Automatycznie wykryj nośniki obrazów" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "Automatyzacja" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "Kopia zapasowa" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "Nazwa katalogu z kopią zapasową:" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "Położenie kopii zapasowej:" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "Utwórz kopię zapasową podczas pobierania zdjęć" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" +"Proszę wybrać katalog pobierania. Podkatalogi dla pobranych zdjęć zostaną w " +"nim automatycznie utworzone w oparciu o poniższą specyfikację." + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" +"Proszę wybrać czy pominąć pobieranie obrazu, czy dodać unikatowy " +"identyfikator." + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "Copyright Damon Lynch 2007-09" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "Początek dnia:" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "Pobierz / Wstrzymaj" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "Katalog pobierania" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "Katalog pobierania:" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "Pobierań dzisiaj:" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "Obsługa błędów" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "Dziennik błędów" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "Zakończ działanie programu po udanym ukończeniu pobierania" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" +"W przypadku wyłączenia wykrywania automatycznego, proszę określić dokładne " +"położenie kopii zapasowej." + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" +"W przypadku wyłączenia wykrywania automatycznego, proszę wybrać dokładne " +"położenie obrazów." + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" +"Jeżeli automatyczne wykrywanie przenośnych magazynów danych jest aktywne, " +"obrazy będą wyszukiwane na całym nośniku. W przypadku nośników o dużych " +"pojemnościach, może to chwilę potrwać." + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "Ignoruj" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "Nośniki obrazów" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "Zmiana nazw obrazów" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" +"Nośniki obrazów to urządzenia z których można pobrać zdjęcia, takie jak " +"aparaty fotograficzne, karty pamięci czy przenośne magazyny danych,\n" +"\n" +"Zdjęcia mogą być pobierane jednocześnie z kilku nośników obrazów.\n" +"\n" +"<i>Jeżeli pobieranie bezpośrednio z aparatu fotograficznego działa " +"nieprawidłowo lub wcale, proszę spróbować przestawić go na tryb PTP. Jeśli " +"jest to niemożliwe, proszę rozważyć użycie czytnika kart pamięci.</i>" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "Położenie obrazów:" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "Importuj obrazy wydajnie i niezawodnie" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "Nadpisz" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "Preferencje: Rapid Photo Downloader" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" +"Program Rapid Photo Downloader jest wolnym oprogramowaniem; można go " +"rozprowadzać dalej i/lub modyfikować na warunkach Powszechnej Licencji " +"Publicznej GNU, wydanej przez Fundację Wolnego Oprogramowania - według " +"wersji drugiej tej Licencji lub którejś z późniejszych wersji.\n" +"\n" +"Program Rapid Photo Downloade rozpowszechniany jest z nadzieją, iż będzie on " +"użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji " +"PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. W celu " +"uzyskania bliższych informacji należy zapoznać się z Powszechną Licencją " +"Publiczną GNU.\n" +"\n" +"Z pewnością wraz z niniejszym programem dostarczono także egzemplarz " +"Powszechnej Licencji Publicznej GNU (GNU General Public License); jeśli nie -" +" proszę napisać do Free Software Foundation, Inc., 51 Franklin Street, Fifth " +"Floor, Boston, MA 02110-130159 USA" + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "Opcje zmiany nazw" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "Zgłoś ostrzeżenie" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "Zgłoś błąd" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "Pomiń" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "Pomiń pobieranie" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" +"Proszę określić katalog dla tego urządzenia w którym przechowywana będzie " +"kopia zapasowa. \n" +"\n" +"<i>Uwaga: zostanie to również wykorzystane do określenia czy urządzenie " +"będzie używane do tworzenia kopii zapasowych. Proszę utworzyć katalog o " +"podanej nazwie dla każdego urządzenia, które będzie używane do zapisu kopii " +"zapasowych.</i>" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" +"Proszę określić czas, w formacie 24-godzinnym, w którym numer sekwencji " +"<i>Pobierań dzisiaj</i> powinien zostać zresetowany." + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" +"Proszę określić zachowanie w przypadku, kiedy obraz o tej samej nazwie " +"został już pobrany lub posiada kopię zapasową." + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "" +"Proszę określić zachowanie w przypadku braku urządzeń na których można " +"utworzyć kopię zapasową." + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" +"Proszę określić czy znaki, które są niedozwolone przez inne systemy " +"operacyjne, powinny zostać usunięte z nazw obrazów i katalogów." + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "Rozpocznij pobieranie przy uruchomieniu programu" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "Rozpocznij pobieranie po podłączeniu nośnika zdjęć" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "Numer zachowany:" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "Usuń niezgodne znaki" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "Odmontuj (\"wysuń\") nośnik zdjęć po ukończeniu pobierania" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" +"Proszę wybrać, czy podczas tworzenia kopii zapasowej nadpisać, czy pominąć " +"obraz o tej samej nazwie na urządzeniu docelowym." + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" +"Możliwe jest utworzenie wielu kopii zapasowych dla pobieranych zdjęć, np. na " +"zewnętrznych dyskach twardych." + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "Wyczyść _ukończone pobierania" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "_Dziennik błędów" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "Z_najdź pomoc w sieci..." + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "_Pomoc" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "_Darowizna" + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "_Zdjęcia" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "Zgłoś _błąd w programie..." + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "_Miniatury" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "_Przetłumacz ten program..." + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "_Widok" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "" + +#~ msgid "" +#~ "There is an error in the program preferences.\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "W preferencjach programu jest błąd.\n" +#~ "Proszę sprawdzić preferencje, uruchomić program ponownie i jeszcze raz " +#~ "spróbować." + +#~ msgid "" +#~ "Image devices are devices from which to download photos, such as memory " +#~ "cards or Portable Storage Devices.\n" +#~ "\n" +#~ "You can download photos from multiple image devices simultaneously." +#~ msgstr "" +#~ "Nośniki obrazów to urządzenia z których można pobrać zdjęcia, takie jak " +#~ "karty pamięci czy przenośne magazyny danych.\n" +#~ "\n" +#~ "Zdjęcia mogą być pobierane jednocześnie z kilku nośników obrazów." + +#~ msgid "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>" +#~ msgstr "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>" + +#~ msgid "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Daniel Plasser <daniel@paessler.org>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>\n" +#~ "Marco Solari <marcosolari@gmail.com>" +#~ msgstr "" +#~ "Julien Valroff <julien@kirya.net>\n" +#~ "Michal Predotka <mpredotka@googlemail.com>\n" +#~ "Martin Egger <martin.egger@gmx.net>\n" +#~ "Daniel Plasser <daniel@paessler.org>\n" +#~ "Abel O'Rian <abel.orian@gmail.com>\n" +#~ "Jose Luis Navarro <jlnavarro111@gmail.com>\n" +#~ "Marco Solari <marcosolari@gmail.com>" diff --git a/po/rapid-photo-downloader.pot b/po/rapid-photo-downloader.pot new file mode 100644 index 0000000..d3c9f0e --- /dev/null +++ b/po/rapid-photo-downloader.pot @@ -0,0 +1,1268 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "" + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "" + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "" + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "" + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "" + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "" + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "" + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "" + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "" + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "" + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "" + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "" + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "" + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "" + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "" + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "" + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr "" + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr "" + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr "" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr "" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "" + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "" + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "" diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..12bf648 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,1378 @@ +# Russian translation for rapid +# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 +# This file is distributed under the same license as the rapid package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: rapid\n" +"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" +"POT-Creation-Date: 2009-05-30 14:31+0800\n" +"PO-Revision-Date: 2009-06-02 18:47+0000\n" +"Last-Translator: Sergei Sedov <sedov@webmail.perm.ru>\n" +"Language-Team: Russian <ru@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2009-06-04 11:00+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63 +msgid "Rapid Photo Downloader" +msgstr "Rapid Photo Downloader" + +#: rapid/rapid.py:392 +msgid "Invalid Downloads Today value.\n" +msgstr "Неверное значение 'Скачиваний сегодня'.\n" + +#: rapid/rapid.py:393 +msgid "Resetting value to zero.\n" +msgstr "Сбросить значение до нуля.\n" + +#: rapid/rapid.py:432 +msgid "'Start of day' preference value is corrupted.\n" +msgstr "Значение 'Начало дня' повреждено.\n" + +#: rapid/rapid.py:433 +msgid "Resetting to midnight.\n" +msgstr "Сброс настроек в полночь.\n" + +#: rapid/rapid.py:457 +msgid "Error in Image Rename preferences" +msgstr "Ошибка в параметрах настройки переименования фотографий" + +#: rapid/rapid.py:466 rapid/rapid.py:1186 +msgid "Sorry,these preferences contain an error:\n" +msgstr "Извините, эти параметры содержат ошибку:\n" + +#: rapid/rapid.py:477 +msgid "Resetting to default values." +msgstr "Восстановить настройки по умолчанию." + +#: rapid/rapid.py:612 +msgid "Error in Download Subfolder preferences" +msgstr "Ошибка в параметрах настройки подкаталогов для сохранения" + +#: rapid/rapid.py:746 +msgid "Select a folder to download photos to" +msgstr "Выберите каталог для сохранения фотографий" + +#: rapid/rapid.py:793 +msgid "Select an image folder" +msgstr "Выберите каталог с фотографиями" + +#: rapid/rapid.py:815 +msgid "Select a folder in which to backup images" +msgstr "Выберите каталог для сохранения резервных копий фотографий" + +#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees +#: rapid/rapid.py:904 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"the name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Внимание:</b> Не хватает метаданных для генерирования названий " +"фотографий. Пожалуйста, используйте другие параметры переименования.</i>" + +#: rapid/rapid.py:924 +msgid "" +"<i><b>Warning:</b> There is insufficient image metatdata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Внимание:</b> Не хватает метаданных для генерирования названий " +"подкаталогов. Пожалуйста, используйте другие параметры переименования.</i>" + +#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see +#: rapid/rapid.py:928 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Пример: %s</i>" + +#: rapid/rapid.py:983 +msgid "The subfolder preferences had some unnecessary values removed." +msgstr "" +"Параметры подкаталогов, имеющих некоторые ненужные значения, были удалены." + +#. Preferences list is now empty +#: rapid/rapid.py:988 +msgid "" +"The subfolder preferences entered are invalid and cannot be used.\n" +"They will be reset to their default values." +msgstr "" +"Введённые параметры подкаталога неправильны и не могут быть использованы.\n" +"Они будут сброшены до значений принятых по умолчанию." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1116 +msgid "externaldrive1" +msgstr "внешний диск 1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/rapid.py:1118 +msgid "externaldrive2" +msgstr "внешний диск 2" + +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for images. It is visible initially in the progress bar for each device +#. (which normally holds "x of y images copied"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1175 +msgid "scanning..." +msgstr "сканирование..." + +#: rapid/rapid.py:1264 rapid/rapid.py:2222 +msgid "There is an error in the program preferences." +msgstr "Обнаружена ошибка в параметрах программы." + +#: rapid/rapid.py:1265 +msgid "" +"\n" +"Please check preferences, restart the program, and try again." +msgstr "" +"\n" +"Пожалуйста, проверьте параметры, перезапустите программу и попробуйте снова." + +#: rapid/rapid.py:1266 rapid/rapid.py:1267 +msgid "Download cannot proceed" +msgstr "Невозможно осуществить скачивание" + +#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. +#. It refers to the actual number of images that can be copied. For example, the user might see the following: +#. '0 of 512 images copied'. +#. This particular text is displayed to the user before the download has started. +#: rapid/rapid.py:1303 rapid/rapid.py:1876 +#, python-format +msgid "0 of %s images copied" +msgstr "0 из %s фотографий скопировано" + +#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. +#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed +#. to the user when they run the program, signifying the number of images found, and the device they were found on. +#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should +#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around +#. in a sentence, but you should never modify them or leave them out. +#: rapid/rapid.py:1315 +#, python-format +msgid "Device scan complete: found %(number)s images on %(device)s" +msgstr "" +"Сканирование носителя завершено: найдено %(number)s фотографий на %(device)s" + +#: rapid/rapid.py:1321 +#, python-format +msgid "Device scan complete: no images found on %s" +msgstr "Сканирование носителя %s завершено: фотографий не найдено" + +#: rapid/rapid.py:1352 +msgid "Image filename could not be generated" +msgstr "Не смог сгенерировать название фотографии" + +#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out +#: rapid/rapid.py:1354 +#, python-format +msgid "" +"Source: %(source)s\n" +"Problem: %(problem)s" +msgstr "" +"Источник: %(source)s\n" +"Проблема: %(problem)s" + +#: rapid/rapid.py:1358 +msgid "" +"Image filename could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Название фотографии не получилось сгенерировать должным образом. Проверьте " +"достаточно ли метаданных." + +#: rapid/rapid.py:1359 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Problem: %(problem)s" +msgstr "" +"Источник: %(source)s\n" +"Получатель: %(destination)s\n" +"Проблема: %(problem)s" + +#: rapid/rapid.py:1368 +msgid "Could not open image" +msgstr "Не смог открыть фотографию" + +#: rapid/rapid.py:1369 +#, python-format +msgid "Source: %s" +msgstr "Источник: %s" + +#: rapid/rapid.py:1378 +msgid "Image has no metadata" +msgstr "Фотография не содержит метаданных" + +#: rapid/rapid.py:1379 +#, python-format +msgid "" +"Metadata is essential for generating subfolders / image names.\n" +"Source: %s" +msgstr "" +"Метаданные необходимы для генерирования названий подкаталогов / " +"фотографий.\n" +"Источник: %s" + +#: rapid/rapid.py:1391 +msgid "" +"Subfolder name could not be properly generated. Check to ensure there is " +"sufficient image metadata." +msgstr "" +"Название подкаталога не получилось сгенерировать должным образом. Проверьте " +"достаточно ли метаданных." + +#: rapid/rapid.py:1392 +#, python-format +msgid "" +"Subfolder: %(subfolder)s\n" +"Image: %(image)s\n" +"Problem: %(problem)s" +msgstr "" +"Подкаталог: %(subfolder)s\n" +"Фотография: %(image)s\n" +"Проблема: %(problem)s" + +#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491 +#: rapid/rapid.py:1553 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Источник: %(source)s\n" +"Получатель: %(destination)s" + +#: rapid/rapid.py:1493 +#, python-format +msgid "Unique identifier '%s' added" +msgstr "Добавлен уникальный идентификатор '%s'" + +#. A new day, according the user's preferences of what time a day begins, has started +#: rapid/rapid.py:1510 +msgid "New day has started - resetting 'Downloads Today' sequence number" +msgstr "" +"Начался новый день - сброшена последовательность номеров параметра " +"'Скачиваний сегодня'" + +#: rapid/rapid.py:1515 rapid/rapid.py:1521 +msgid "Download copying error" +msgstr "Ошибка при закачке файлов" + +#: rapid/rapid.py:1516 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errorno)s %(strerror)s" +msgstr "" +"Источник: %(source)s\n" +"Получатель: %(destination)s\n" +"Ошибка: %(errorno)s %(strerror)s" + +#: rapid/rapid.py:1518 rapid/rapid.py:1591 +msgid "The image was not copied." +msgstr "Фотография не скопирована." + +#: rapid/rapid.py:1552 +msgid "Backup image already exists" +msgstr "Носитель для резервного копирования фотографий уже существует" + +#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594 +msgid "Backing up error" +msgstr "Ошибка резервного копирования" + +#: rapid/rapid.py:1581 +#, python-format +msgid "" +"Destination directory could not be created\n" +"%(directory)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Невозможно создать каталог получателя\n" +"%(directory)s\n" +"Ошибка: %(errno)s %(strerror)s" + +#: rapid/rapid.py:1589 rapid/rapid.py:1595 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s\n" +"Error: %(errno)s %(strerror)s" +msgstr "" +"Источник: %(source)s\n" +"Получатель: %(destination)s\n" +"Ошибка: %(errno)s %(strerror)s" + +#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it +#: rapid/rapid.py:1608 +msgid "The device can now be safely removed" +msgstr "Теперь можно безопасно отсоединить носитель" + +#: rapid/rapid.py:1612 +#, python-format +msgid "%s images downloaded" +msgstr "%s фотографий скачано" + +#: rapid/rapid.py:1614 +#, python-format +msgid "%s images skipped" +msgstr "%s фотографий пропущено" + +#: rapid/rapid.py:1620 rapid/rapid.py:2707 +msgid "warnings" +msgstr "предупреждения" + +#: rapid/rapid.py:1622 rapid/rapid.py:2709 +msgid "errors" +msgstr "ошибки" + +#: rapid/rapid.py:1644 +msgid "Backup device missing" +msgstr "Пропущен носитель для резервного копирования" + +#: rapid/rapid.py:1644 +msgid "No backup device was detected." +msgstr "Устройство для сохранения резервных копий не обнаружено" + +#: rapid/rapid.py:1648 +msgid "This device has no images to download from." +msgstr "На этом устройстве не обнаружены фотографии, которые можно скачать." + +#: rapid/rapid.py:1674 +#, python-format +msgid "Download has started from %s" +msgstr "Начато скачивание с %s" + +#: rapid/rapid.py:1711 +msgid "Image skipped" +msgstr "Фотография пропущена" + +#: rapid/rapid.py:1712 +msgid "Image overwritten" +msgstr "Фотография перезаписана" + +#: rapid/rapid.py:1713 +msgid "Image already exists" +msgstr "Фотография уже существует" + +#: rapid/rapid.py:1758 +msgid "Image has no thumbnail" +msgstr "У фотографии нет предпросмотра" + +#: rapid/rapid.py:1768 +#, python-format +msgid "%(number)s of %(total)s images copied" +msgstr "%(number)s из %(total)s фотографий скопировано" + +#: rapid/rapid.py:1784 +#, python-format +msgid "Download complete from %s" +msgstr "Скачивание с %s завершено" + +#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:1860 +msgid "Device" +msgstr "Носитель" + +#. Size refers to the total size of images on the device, typically in MB or GB +#: rapid/rapid.py:1865 +msgid "Size" +msgstr "Размер" + +#: rapid/rapid.py:1868 +msgid "Download Progress" +msgstr "Скачано" + +#: rapid/rapid.py:1984 rapid/rapid.py:1990 +msgid "Thumbnail cannot be displayed" +msgstr "Предпросмотр фотографии не может быть выполнен" + +#: rapid/rapid.py:1985 rapid/rapid.py:1991 +msgid "It may be corrupted" +msgstr "Возможно он повреждён" + +#: rapid/rapid.py:2223 +msgid "Some preferences will be reset." +msgstr "Некоторые параметры будут сброшены." + +#: rapid/rapid.py:2251 +msgid "" +"A newer version of this program was previously run on this computer.\n" +"\n" +msgstr "" +"На этом компьютере ранее запускалась более новая версия программы.\n" +"\n" + +#: rapid/rapid.py:2253 +msgid "" +"Program preferences appear to be valid, but please check them to ensure " +"correct operation." +msgstr "" +"Параметры программы кажется корректны, но, пожалуйста, проверьте их, чтобы " +"быть уверенными в правильности." + +#: rapid/rapid.py:2255 +msgid "Sorry, some preferences are invalid and will be reset." +msgstr "Извините, некоторые параметры были неправильными и будут сброшены." + +#: rapid/rapid.py:2256 +msgid "Warning:" +msgstr "Предупреждение:" + +#: rapid/rapid.py:2261 +msgid "" +"This version of the program is newer than the previously run version. " +"Checking preferences." +msgstr "" +"Эта версия программы новее чем запущенная ранее. Проверьте параметры." + +#: rapid/rapid.py:2268 +msgid "Preferences were modified." +msgstr "Параметры были изменены" + +#: rapid/rapid.py:2269 +msgid "" +"This version of the program uses different preferences than the old version. " +"Your preferences have been updated.\n" +"\n" +"Please check them to ensure correct operation." +msgstr "" +"Эта версия программы использует несколько другие параметры, чем предыдущая. " +"Параметры были автоматически обновлены.\n" +"\n" +"Пожалуйста, проверьте их, чтобы быть уверенными, что всё прошло правильно." + +#: rapid/rapid.py:2273 +msgid "No preferences needed to be changed." +msgstr "Отсутствуют параметры, которые необходимо было бы изменить." + +#: rapid/rapid.py:2275 +msgid "" +"This version of the program uses different preferences than the old version. " +"Some of your previous preferences were invalid, and could not be updated. " +"They will be reset." +msgstr "" +"Эта версия программы использует несколько другие параметры, чем предыдущая. " +"Некоторые из ваших параметров были не верными. Они будут сброшены." + +#: rapid/rapid.py:2284 +msgid "Problem using pynotify." +msgstr "Проблема при использовании pynotify." + +#: rapid/rapid.py:2300 +msgid "Failed to receive pynotify server capabilities." +msgstr "Не удалось получить возможности сервера pynotify." + +#: rapid/rapid.py:2338 +msgid "and" +msgstr "и" + +#: rapid/rapid.py:2343 +msgid "Using backup devices" +msgstr "Использование носителя для резервного копирования" + +#: rapid/rapid.py:2345 +msgid "Using backup device" +msgstr "Использование носителя для резервного копирования" + +#: rapid/rapid.py:2347 +msgid "No backup devices detected" +msgstr "Не обнаружено носителей для создания резервных копий" + +#: rapid/rapid.py:2482 +#, python-format +msgid "Detected %(device)s with path %(path)s" +msgstr "Обнаружено %(device)s с путём %(path)s" + +#: rapid/rapid.py:2486 +msgid "Automatically start download is true" +msgstr "Автоматически начинать скачивание - да" + +#: rapid/rapid.py:2488 +msgid "Automatically start download is false" +msgstr "Автоматически начинать скачивание - нет" + +#: rapid/rapid.py:2536 +msgid "Using manually specified path" +msgstr "Использовать путь, который указан вручную" + +#: rapid/rapid.py:2653 rapid/rapid.py:2702 +msgid "All downloads complete" +msgstr "Все скачивания завершены" + +#: rapid/rapid.py:2667 +msgid "MB/s" +msgstr "Мб/с" + +#: rapid/rapid.py:2677 +msgid "About 1 second remaining" +msgstr "Осталась примерно 1 секунда" + +#: rapid/rapid.py:2679 +#, python-format +msgid "About %i seconds remaining" +msgstr "Осталось %i секунд" + +#: rapid/rapid.py:2681 +msgid "About 1 minute remaining" +msgstr "Осталась примерно 1 минута" + +#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. +#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount +#. of time the download has remainging, e.g. 'About 5:36 minutes remaining' +#: rapid/rapid.py:2686 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Осталось примерно %(minutes)i:%(seconds)02i" + +#: rapid/rapid.py:2703 +msgid "images downloaded" +msgstr "фотографий скачано" + +#: rapid/rapid.py:2705 +msgid "images skipped" +msgstr "фотографий пропущено" + +#. This text will be displayed to the user on the Download / Pause button. +#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines +#: rapid/rapid.py:2797 +msgid "_Download " +msgstr "_Скачать " + +#. This text will be displayed to the user on the Download / Pause button. +#: rapid/rapid.py:2807 +msgid "_Pause" +msgstr "_Пауза" + +#: rapid/rapid.py:2862 +msgid "Preferences were changed." +msgstr "Параметры были изменены" + +#: rapid/rapid.py:2993 +msgid "Goodbye" +msgstr "До свидания" + +#. Translators: this text is displayed to the user when they request information on the command line options. +#. The text %default should not be modified or left out. +#: rapid/rapid.py:3004 +#, python-format +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" +"отобразить информацию о программе в командной строке при запуске программы " +"(по умолчанию: %default)" + +#: rapid/rapid.py:3005 +msgid "only output errors to the command line" +msgstr "выводить в командную строку только ошибки" + +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3007 +msgid "list image file extensions the program recognizes and exit" +msgstr "" +"вывести расширения файла фотографии, которые распознала программа и выйти" + +#: rapid/rapid.py:3020 +#, python-format +msgid "and %s" +msgstr "и %s" + +#. Which volume management code is being used (GIO or GnomeVFS) +#: rapid/rapid.py:3025 rapid/rapid.py:3028 +msgid "Using" +msgstr "Использование" + +#. this application is already running +#: rapid/rapid.py:3042 +#, python-format +msgid "%s is already running" +msgstr "%s уже запущено" + +#: rapid/renamesubfolderprefs.py:176 +msgid "Date time" +msgstr "Дата и время" + +#: rapid/renamesubfolderprefs.py:177 +msgid "Text" +msgstr "Текст" + +#: rapid/renamesubfolderprefs.py:178 +msgid "Filename" +msgstr "Имя файла" + +#: rapid/renamesubfolderprefs.py:179 +msgid "Metadata" +msgstr "Метаданные" + +#: rapid/renamesubfolderprefs.py:180 +msgid "Sequences" +msgstr "Последовательности" + +#: rapid/renamesubfolderprefs.py:181 +msgid "Image date" +msgstr "Дата фотографии" + +#: rapid/renamesubfolderprefs.py:182 +msgid "Today" +msgstr "Сегодня" + +#: rapid/renamesubfolderprefs.py:183 +msgid "Yesterday" +msgstr "Вчера" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:185 +msgid "Name + extension" +msgstr "Имя + расширение" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:187 +msgid "Name" +msgstr "Имя" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:189 +msgid "Extension" +msgstr "Расширение" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:191 +msgid "Image number" +msgstr "Номер фотографии" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:193 +msgid "Aperture" +msgstr "Диафрагма" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:195 +msgid "ISO" +msgstr "ISO" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:197 +msgid "Exposure time" +msgstr "Время выдержки" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:199 +msgid "Focal length" +msgstr "Фокусное расстояние" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:201 +msgid "Camera make" +msgstr "Производитель камеры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:203 +msgid "Camera model" +msgstr "Модель камеры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:205 +msgid "Short camera model" +msgstr "Сокращённое название камеры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:207 +msgid "Hyphenated short camera model" +msgstr "Расширенное название камеры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:209 +msgid "Serial number" +msgstr "Серийный номер" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:211 +msgid "Shutter count" +msgstr "Счётчик кадров" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/renamesubfolderprefs.py:213 +msgid "Owner name" +msgstr "Имя владельца" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:215 +msgid "Downloads today" +msgstr "Скачиваний сегодня" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:217 +msgid "Session number" +msgstr "Номер сессии" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:219 +msgid "Subfolder number" +msgstr "Номер подкаталога" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/renamesubfolderprefs.py:221 +msgid "Stored number" +msgstr "Сохранение под номером" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/renamesubfolderprefs.py:223 +msgid "Sequence letter" +msgstr "Последовательность символов" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:225 +msgid "All digits" +msgstr "Все цифры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:227 +msgid "Last digit" +msgstr "Последняя цифра" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:229 +msgid "Last 2 digits" +msgstr "Последние 2 цифры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:231 +msgid "Last 3 digits" +msgstr "Последние 3 цифры" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/renamesubfolderprefs.py:233 +msgid "Last 4 digits" +msgstr "Последние 4 цифры" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:235 +msgid "Original Case" +msgstr "Исходный Регистр" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:237 +msgid "UPPERCASE" +msgstr "ВЕРХНИЙ РЕГИСТР" + +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/renamesubfolderprefs.py:239 +msgid "lowercase" +msgstr "нижний регистр" + +#: rapid/renamesubfolderprefs.py:240 +msgid "One digit" +msgstr "Одна цифра" + +#: rapid/renamesubfolderprefs.py:241 +msgid "Two digits" +msgstr "Две цифры" + +#: rapid/renamesubfolderprefs.py:242 +msgid "Three digits" +msgstr "Три цифры" + +#: rapid/renamesubfolderprefs.py:243 +msgid "Four digits" +msgstr "Четыре цифры" + +#: rapid/renamesubfolderprefs.py:244 +msgid "Five digits" +msgstr "Пять цифр" + +#: rapid/renamesubfolderprefs.py:245 +msgid "Six digits" +msgstr "Шесть цифр" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:247 +msgid "Subseconds" +msgstr "Подсекунды" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:249 +msgid "YYYYMMDD" +msgstr "ГГГГММДД" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:251 +msgid "YYYY-MM-DD" +msgstr "ГГГГ-ММ-ДД" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:253 +msgid "YYMMDD" +msgstr "ГГММДД" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:255 +msgid "YY-MM-DD" +msgstr "ГГ-ММ-ДД" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:257 +msgid "MMDDYYYY" +msgstr "ММДДГГГГ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:259 +msgid "MMDDYY" +msgstr "ММДДГГ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:261 +msgid "MMDD" +msgstr "ММДД" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:263 +msgid "DDMMYYYY" +msgstr "ДДММГГГГ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:265 +msgid "DDMMYY" +msgstr "ДДММГГ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:267 +msgid "YYYY" +msgstr "ГГГГ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:269 +msgid "YY" +msgstr "ГГ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:271 +msgid "MM" +msgstr "ММ" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:273 +msgid "DD" +msgstr "ДД" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:275 +msgid "HHMMSS" +msgstr "ЧЧММСС" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/renamesubfolderprefs.py:277 +msgid "HHMM" +msgstr "ЧЧММ" + +#: rapid/renamesubfolderprefs.py:682 +#, python-format +msgid "" +"Preference key '%(key)s' is invalid.\n" +"Expected one of %(value)s" +msgstr "" +"Неверен ключ параметров '%(key)s'.\n" +"Ожидался один из %(value)s" + +#: rapid/renamesubfolderprefs.py:689 +#, python-format +msgid "Preference value '%(value)s' is invalid" +msgstr "Неверное значение параметра '%(value)s'" + +#: rapid/renamesubfolderprefs.py:693 +msgid "These preferences are not well formed:" +msgstr "Эти параметры не очень хорошо подобраны:" + +#: rapid/renamesubfolderprefs.py:793 +msgid "Subsecond metadata not present in image" +msgstr "Метаданные подсекунд не представлены в фотографии" + +#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919 +#, python-format +msgid "%s metadata is not present in image" +msgstr "%s метаданные не представлены в фотографии" + +#: rapid/renamesubfolderprefs.py:811 +#, python-format +msgid "Error in date time component. Value %s appears invalid" +msgstr "Ошибка в компоненте даты и времени. Значение %s неверно." + +#: rapid/renamesubfolderprefs.py:842 +msgid "extension was specified but image name has no extension" +msgstr "расширение было указано, но фотографий не имеет расширения" + +#: rapid/renamesubfolderprefs.py:846 +msgid "image number was specified but image filename has no number" +msgstr "номер фотографии был указано, но фотография не имеет номер" + +#: rapid/renamesubfolderprefs.py:1031 +#, python-format +msgid "error generating name with component %s" +msgstr "ошибка генерирования названия компонентом %s" + +#: rapid/renamesubfolderprefs.py:1327 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Параметры подкаталога не должны начинаться с %s" + +#: rapid/renamesubfolderprefs.py:1329 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Параметры подкаталога не должны заканчиваться с %s" + +#: rapid/renamesubfolderprefs.py:1333 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "Параметры подкаталога не должны содержать две %s одну за другой" + +#: rapid/glade3/rapid.glade.h:1 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:2 +msgid " " +msgstr " " + +#: rapid/glade3/rapid.glade.h:3 +msgid " hh:mm" +msgstr " чч:мм" + +#: rapid/glade3/rapid.glade.h:4 +msgid ":" +msgstr ":" + +#: rapid/glade3/rapid.glade.h:5 +msgid "<b>Backup</b>" +msgstr "<b>Резервное копирование</b>" + +#: rapid/glade3/rapid.glade.h:6 +msgid "<b>Compatibility with Other Operating Systems</b>" +msgstr "<b>Совместимость с другими операционными системами</b>" + +#: rapid/glade3/rapid.glade.h:7 +msgid "<b>Download Folder</b>" +msgstr "<b>Каталог сохранения</b>" + +#: rapid/glade3/rapid.glade.h:8 +msgid "<b>Download Subfolders</b>" +msgstr "<b>Подкаталоги сохранения</b>" + +#: rapid/glade3/rapid.glade.h:9 +msgid "<b>Example</b>" +msgstr "<b>Пример</b>" + +#: rapid/glade3/rapid.glade.h:10 +msgid "<b>Image Devices</b>" +msgstr "<b>Носители фотографий</b>" + +#: rapid/glade3/rapid.glade.h:11 +msgid "<b>Image Name Conflicts</b>" +msgstr "<b>Конфликты в названии фотографии</b>" + +#: rapid/glade3/rapid.glade.h:12 +msgid "<b>Image Rename</b>" +msgstr "<b>Переименование фотографий</b>" + +#: rapid/glade3/rapid.glade.h:13 +msgid "<b>Missing Backup Devices</b>" +msgstr "<b>Отсутствующие носители резервного копирования</b>" + +#: rapid/glade3/rapid.glade.h:14 +msgid "<b>Program Automation</b>" +msgstr "<b>Автоматизация программы</b>" + +#: rapid/glade3/rapid.glade.h:15 +msgid "<b>Sequence numbers</b>" +msgstr "<b>Последовательность чисел</b>" + +#: rapid/glade3/rapid.glade.h:16 +msgid "<i>/media/externaldrive/Photos</i>" +msgstr "<i>/media/externaldrive/Photos</i>" + +#: rapid/glade3/rapid.glade.h:17 +msgid "<i>Example: /home/user/photos</i>" +msgstr "<i>Пример: /home/user/photos</i>" + +#: rapid/glade3/rapid.glade.h:18 +msgid "<i>Example:</i>" +msgstr "<i>Пример:</i>" + +#: rapid/glade3/rapid.glade.h:19 +msgid "<i>New:</i>" +msgstr "<i>Новое название:</i>" + +#: rapid/glade3/rapid.glade.h:20 +msgid "<i>Original:</i>" +msgstr "<i>Оригинальное название:</i>" + +#: rapid/glade3/rapid.glade.h:21 +msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Автоматизация</span>" + +#: rapid/glade3/rapid.glade.h:22 +msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Резервное копирование</span>\t" + +#: rapid/glade3/rapid.glade.h:23 +msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Каталог сохранения</span>" + +#: rapid/glade3/rapid.glade.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Обработка ошибок</span>" + +#: rapid/glade3/rapid.glade.h:25 +msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Носители фотографий</span>" + +#: rapid/glade3/rapid.glade.h:26 +msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Переименование фотографий</span>\t" + +#: rapid/glade3/rapid.glade.h:27 +msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" +msgstr "" +"<span weight=\"bold\" size=\"x-large\">Параметры переименования</span>" + +#: rapid/glade3/rapid.glade.h:28 +msgid "Add unique identifier" +msgstr "Добавить уникальный идентификатор" + +#: rapid/glade3/rapid.glade.h:29 +msgid "Automatically detect Portable Storage Devices" +msgstr "Автоматически определять внешние съёмные носители" + +#: rapid/glade3/rapid.glade.h:30 +msgid "Automatically detect backup devices" +msgstr "Автоматически определять носители для резервного копирования" + +#: rapid/glade3/rapid.glade.h:31 +msgid "Automatically detect image devices" +msgstr "Автоматически определять носители, которые содержат фотографии" + +#: rapid/glade3/rapid.glade.h:32 +msgid "Automation" +msgstr "Автоматизация" + +#: rapid/glade3/rapid.glade.h:33 +msgid "Backup" +msgstr "Резервное копирование" + +#: rapid/glade3/rapid.glade.h:34 +msgid "Backup folder name:" +msgstr "Название каталога:" + +#: rapid/glade3/rapid.glade.h:35 +msgid "Backup location:" +msgstr "Местоположение резервных копий" + +#: rapid/glade3/rapid.glade.h:36 +msgid "Backup photos when downloading" +msgstr "Выполнять резервное копирование фотографий при их скачивании" + +#: rapid/glade3/rapid.glade.h:37 +msgid "" +"Choose the download folder. Subfolders for the downloaded photos will be " +"automatically created in this folder using the structure specified below." +msgstr "" +"Выберите каталог, где будут храниться фотографии. Подкаталоги для " +"скачиваемых фотографий будут автоматически созданы в каждом каталоге, " +"используя структуру указанную ниже." + +#: rapid/glade3/rapid.glade.h:38 +msgid "" +"Choose whether to skip downloading the image, or to add a unique indentifier." +msgstr "" +"Выберите пропустить ли скачивание фотографий или добавить к ней уникальный " +"идентификатор." + +#: rapid/glade3/rapid.glade.h:39 +msgid "Copyright Damon Lynch 2007-09" +msgstr "Copyright Damon Lynch 2007-09" + +#: rapid/glade3/rapid.glade.h:40 +msgid "Day start:" +msgstr "Начало дня:" + +#: rapid/glade3/rapid.glade.h:41 +msgid "Download / Pause" +msgstr "Скачать / Пауза" + +#: rapid/glade3/rapid.glade.h:42 +msgid "Download Folder" +msgstr "Каталог сохранения" + +#: rapid/glade3/rapid.glade.h:43 +msgid "Download folder:" +msgstr "Каталог сохранения:" + +#: rapid/glade3/rapid.glade.h:44 +msgid "Downloads today:" +msgstr "Скачиваний сегодня:" + +#: rapid/glade3/rapid.glade.h:45 +msgid "Error Handling" +msgstr "Обработка ошибок" + +#: rapid/glade3/rapid.glade.h:46 +msgid "Error Log" +msgstr "Журнал ошибок" + +#: rapid/glade3/rapid.glade.h:47 +msgid "Exit program after completion of successful download" +msgstr "Выйти из программы после успешного завершения скачивания фотографий" + +#: rapid/glade3/rapid.glade.h:48 +msgid "If you disable automatic detection, choose the exact backup location." +msgstr "" +"Если вы отключаете автоматическое определение, то, пожалуйста, выберите " +"точное местоположение носителя для резервного копирования." + +#: rapid/glade3/rapid.glade.h:49 +msgid "" +"If you disable automatic detection, choose the exact location of the images." +msgstr "" +"Если вы отключаете автоматическое определение, то, пожалуйста, выберите " +"точное местоположение фотографий." + +#: rapid/glade3/rapid.glade.h:50 +msgid "" +"If you enable automatic detection of Portable Storage Devices, the entire " +"device will be scanned for images. On large devices, this could take some " +"time." +msgstr "" +"Если вы включите автоматическое определение съёмных носителей, то будьте " +"готовы к тому, что они будут просканированы на наличие фотографий. На " +"носителях большого объёма это может занять достаточно много времени." + +#: rapid/glade3/rapid.glade.h:51 +msgid "Ignore" +msgstr "Игнорировать" + +#: rapid/glade3/rapid.glade.h:52 +msgid "Image Devices" +msgstr "Носители фотографий" + +#: rapid/glade3/rapid.glade.h:53 +msgid "Image Rename" +msgstr "Переименование фотографий" + +#: rapid/glade3/rapid.glade.h:54 +msgid "" +"Image devices are devices from which to download photos, such as cameras, " +"memory cards or Portable Storage Devices.\n" +"\n" +"You can download photos from multiple image devices simultaneously.\n" +"\n" +"<i>If downloading directly from your camera works poorly or not at all, try " +"setting it to PTP mode. If that is not possible, consider using a card " +"reader.</i>" +msgstr "" +"Носители фотографий - это устройства с которых необходимо скачать " +"фотографии, например фотоаппараты, карты памяти или съёмные носители. \n" +"\n" +"Вы можете одновременно скачивать фотографии с нескольких носителей.\n" +"\n" +"<i>Скачивание непосредственно из фотоаппарата может работать медленно или не " +"работать совсем, в этом случае попытайтесь установить его в режим PTP. Если " +"это не возможно, то попробуйте использовать устройство для чтения карт " +"памяти.</i>" + +#: rapid/glade3/rapid.glade.h:59 +msgid "Image location:" +msgstr "Местоположение фотографий:" + +#: rapid/glade3/rapid.glade.h:60 +msgid "Import your images efficiently and reliably" +msgstr "Эффективное и надёжное импортирование ваших фотографий" + +#: rapid/glade3/rapid.glade.h:61 +msgid "Overwrite" +msgstr "Перезаписать" + +#: rapid/glade3/rapid.glade.h:62 +msgid "Preferences: Rapid Photo Downloader" +msgstr "Параметры: Rapid Photo Downloader" + +#: rapid/glade3/rapid.glade.h:64 +msgid "" +"Rapid Photo Downloader is free software; you can redistribute it and/or " +"modify it under the terms of the GNU General Public License as published by " +"the Free Software Foundation; either version 2 of the License, or (at your " +"option) any later version.\n" +"\n" +"Rapid Photo Downloader is distributed in the hope that it will be useful, " +"but WITHOUT ANY WARRANTY; without even the implied warranty of " +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General " +"Public License for more details.\n" +"\n" +"You should have received a copy of the GNU General Public License along with " +"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., " +"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." +msgstr "" +"Rapid Photo Downloader - это бесплатное программное обеспечение; вы можете " +"передавать его и/или модифицировать в соответствии с соглашением GNU General " +"Public License опубликованным Free Software Foundation версии 2 или (по " +"вашему выбору) более поздней версии.\n" +"\n" +"Rapid Photo Downloader распространяется с верой в то, что эта программа " +"будет полезна вам, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ и даже без гарантий " +"КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ КАКОГО-ЛИБО ОПРЕДЕЛЁННОГО " +"ИСПОЛЬЗОВАНИЯ. Для дополнительной информации читайте GNU General Public " +"License.\n" +"\n" +"Вы должны были получить копию GNU General Public License вместе с Rapid " +"Photo Downloader; если вы не получили её, то вы можете написать в Free " +"Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-" +"1301, USA." + +#: rapid/glade3/rapid.glade.h:69 +msgid "Rename Options" +msgstr "Параметры переименования" + +#: rapid/glade3/rapid.glade.h:70 +msgid "Report a warning" +msgstr "Предупредить" + +#: rapid/glade3/rapid.glade.h:71 +msgid "Report an error" +msgstr "Сообщить об ошибке" + +#: rapid/glade3/rapid.glade.h:72 +msgid "Skip" +msgstr "Пропустить" + +#: rapid/glade3/rapid.glade.h:73 +msgid "Skip download" +msgstr "Пропустить скачивание" + +#: rapid/glade3/rapid.glade.h:74 +msgid "" +"Specify the folder in which backups are stored on the device. \n" +"\n" +"<i>Note: this will also be used to determine whether or not the device is " +"used for backups. For each device you wish to use for backing up to, create " +"a folder in it with this name.</i>" +msgstr "" +"Укажите каталог для хранения резервных копий фотографий на устройстве.\n" +"\n" +"<i>Примечание: На каждом носителе, который вы хотите использовать для " +"резервного копирования, создайте каталог с этим названием.</i>" + +#: rapid/glade3/rapid.glade.h:77 +msgid "" +"Specify the time in 24 hour format at which the <i>Downloads today</i> " +"sequence number should be reset." +msgstr "" +"Укажите время в 24 часовом формате, в которое будет сброшена " +"последовательность номеров параметра <i>Скачиваний сегодня</i>." + +#: rapid/glade3/rapid.glade.h:78 +msgid "" +"Specify what to do when an image of the same name has already been " +"downloaded or backed up." +msgstr "" +"Укажите, как следует поступить с фотографией, имеющей точно такое же " +"название и уже скачанной или сохранённой в резервной копии." + +#: rapid/glade3/rapid.glade.h:79 +msgid "Specify what to do when there are no backup devices." +msgstr "" +"Укажите, что делать если не обнаружены носители для резервного копирования." + +#: rapid/glade3/rapid.glade.h:80 +msgid "" +"Specify whether image and folder names should have any characters removed " +"that are not allowed by other operating systems." +msgstr "" +"Укажите, должны ли удаляться символы в наименованиях фотографий и каталогов, " +"которые не распознаются в других операционных системах." + +#: rapid/glade3/rapid.glade.h:81 +msgid "Start downloading at program startup" +msgstr "Начать скачивание фотографий сразу после запуска программы" + +#: rapid/glade3/rapid.glade.h:82 +msgid "Start downloading upon image device insertion" +msgstr "Начать скачивание фотографий при вставке носителя" + +#: rapid/glade3/rapid.glade.h:83 +msgid "Stored number:" +msgstr "Сохранение под номером:" + +#: rapid/glade3/rapid.glade.h:84 +msgid "Strip incompatible characters" +msgstr "Убрать несовместимые символы" + +#: rapid/glade3/rapid.glade.h:85 +msgid "Unmount (\"eject\") image device upon download completion" +msgstr "" +"Отсоединить (\"извлечь\") носитель с фотографиями после завершения скачивания" + +#: rapid/glade3/rapid.glade.h:86 +msgid "" +"When backing up, choose whether to overwrite an image on the backup device " +"that has the same name, or skip backing it up." +msgstr "" +"Во время резервного копирования могут встретиться фотографии с одинаковыми " +"именами. Выберите, перезаписать ли такую фотографию или пропустить её." + +#: rapid/glade3/rapid.glade.h:87 +msgid "" +"You can have your photos backed up to multiple locations as they are " +"downloaded, e.g. external hard drives." +msgstr "" +"Вы можете производить резервное копирование фотографий на различные " +"носители, в том числе на внешние жёсткие диски." + +#: rapid/glade3/rapid.glade.h:88 +msgid "_Clear Completed Downloads" +msgstr "_Очистить завершённые скачивания" + +#: rapid/glade3/rapid.glade.h:89 +msgid "_Error Log" +msgstr "_Журнал ошибок" + +#: rapid/glade3/rapid.glade.h:90 +msgid "_Get Help Online..." +msgstr "_Получить помощь в интернете..." + +#: rapid/glade3/rapid.glade.h:91 +msgid "_Help" +msgstr "_Помощь" + +#: rapid/glade3/rapid.glade.h:92 +msgid "_Make a Donation..." +msgstr "_Сделать пожервование" + +#: rapid/glade3/rapid.glade.h:93 +msgid "_Photos" +msgstr "_Фотографии" + +#: rapid/glade3/rapid.glade.h:94 +msgid "_Report a Problem..." +msgstr "_Сообщить о проблеме..." + +#: rapid/glade3/rapid.glade.h:95 +msgid "_Thumbnails" +msgstr "_Предпросмотр фотографий" + +#: rapid/glade3/rapid.glade.h:96 +msgid "_Translate this Application..." +msgstr "_Перевести это приложение..." + +#: rapid/glade3/rapid.glade.h:97 +msgid "_View" +msgstr "_Просмотр" + +#: rapid/glade3/rapid.glade.h:98 +msgid "translators please ignore this" +msgstr "" diff --git a/rapid-photo-downloader b/rapid-photo-downloader new file mode 100755 index 0000000..87e63c0 --- /dev/null +++ b/rapid-photo-downloader @@ -0,0 +1,5 @@ +#!/usr/bin/python + +import rapid.rapid + +rapid.rapid.start () diff --git a/rapid/AUTHORS b/rapid/AUTHORS new file mode 100644 index 0000000..c89d793 --- /dev/null +++ b/rapid/AUTHORS @@ -0,0 +1 @@ +Damon Lynch <damonlynch@gmail.com> diff --git a/rapid/COPYING b/rapid/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/rapid/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/rapid/ChangeLog b/rapid/ChangeLog new file mode 100644 index 0000000..430aab8 --- /dev/null +++ b/rapid/ChangeLog @@ -0,0 +1,393 @@ +Version 0.0.10 +-------------- + +2009-06-05 + +Updated Russian translation by Sergei Sedov. + +Fixed bug #383028: program would crash when using an automatically configured +backup device and gvfs. + + + +Version 0.0.9 +------------- + +2009-06-02 + +Added Italian translation by Marco Solari and Luca Reverberi. + +Added German translation by Martin Egger and Daniel Passler. + +Added Russian translation by Sergei Sedov. + +Added Finnish translation by Mikko Ruohola. + +A Help button has been added to Preferences dialog window. Clicking it takes you +to the documentation found online at the program's website. This documentation +is now complete. + +The Preferences Dialog Window is now navigated using a list control, as it was +in early versions of the program. This change was necesseary because with some +translations, the dialog window was becoming too wide with the normal tab +layout. Usability of the preferences dialog is improved: it will now resize +itself based on its content. + +Better integration with Nautilus is now possible through the setting of +MimeType=x-content/image-dcf in the program's .desktop file. + + + +Version 0.0.9 beta 4 +-------------------- + +2009-05-26 + +Added Spanish translation by Jose Luis Navarro and Abel O'Rian. + +Whenever subfolder preferences are modified in the Preferences Dialog window, +they are now checked to see if they contain any extraneous entries. If +necessary, any entries like this are removed when the dialog window is closed. + +Bug fix: Changes in preferences should be applied to devices that have already +been scanned, but their images not yet downloaded. This bug was introduced in +beta 2 when fixing bug #368098. + +Bug fix: check subfolder preferences for validity before beginning download. +While image rename preferences were checked, this check was neglected. + +Bug fix: do not allow automatic downloading when there is an error in the +preferences. + + + +Version 0.0.9 beta 3 +-------------------- + +2009-05-25 + +Added command line options for controlling verbosity, displaying which image +file types are recognized, and printing the program version. + +Updated man page to reflect recent program changes and new command line options. + +Prepared program for translation into other languages. Thanks go to Mark Mruss +and his blog http://www.learningpython.com for code examples and explanations. + +Polish translation by Michal Predotka. Coming soon: French, German and +Spanish translations. + +To install the program using python setup.py, the program msgfmt must now be +present. On most Linux distributions, this is found in the package gettext. + +Updated INSTALL file to reflect minimum version of pyexiv2 needed, and included +information about handling any error related to msgfmt not being installed. + +Minor fixes to logic that checks whether the Download button should be disabled +or not. This should now be more reliable. + +Bug fix: error log window can now be reopened after being closed with the "x" +button. Thanks go to ESR and his Python FAQ entry for this fix. + +Bug fix: example of subfolder name now has word wrap. Thanks go to Michal +Predotka for reporting this. + +Bug fix: don't crash when a thumbnail image is missing and the 'orientation' +variable has not yet been assigned. + + + +Version 0.0.9 beta 2 +-------------------- + +2009-05-12 + +By popular demand, allow direct downloading from cameras. This support is +experimental and may not work with your camera. This is possible through the use +of the new gvfs service, provided by GIO, that exists in recent versions of +Linux. A recent version of Linux is a must. The camera must also be supported by +libgphoto2 in combination with gvfs. If you cannot browse the camera's contents +in a file manager (e.g. Nautilus), the camera download will not work until the +gvfs support is improved. + +Although this is a popular request, the reality is that downloading images +directly from the camera is often extremely slow in comparison to popping the +memory card into a card reader and downloading from that. + +Fix bug #368098: the program now starts more quickly and does not become +unresponsive when scanning devices with a large number of images. This will +hardly be noticeable by users that download from memory cards, but for those +who download from hard drives with hundreds of GBs of files -- they'll notice +a big difference. + +Fix bug #372284: for image renaming, the "image number" component is more +robust. Now, only the series of digits at the end of a filename are recognized +as the image number (obviously the file's extension is not included as being +part of the filename in this case). This allows takes in account files from +cameras like the Canon 1D series, which can have filenames like VD1D7574.CR2. + +Bug fix: don't download from volumes mounted while the program is already +running unless auto detection is specified. This bug could occur when auto +detection was enabled, then disabled, and then a volume was mounted. + + + +Version 0.0.8 +------------- + +2009-05-01 + +Added stored and downloads today sequence numbers: + +* The stored sequence number is remembered each time the program is run. + +* Downloads today tracks how many downloads are made on a given day. The time a + day "starts" is set via a new preference value, day start. This is useful if + you often photograph something late at night (e.g. concerts) and want a new + day to "start" at 3am, for instance. + +Make estimate of time remaining to download images much more accurate. + +Display download speed in status bar. + +Reorganized sequence number/letter selection in preferences. + +Add feature to detect change in program version, upgrading preferences where +necessary. + +Only allow one instance of the program to be run -- raise existing window if it +is run again. This is very useful when Rapid Photo Downloader is set to run +automatically upon insertion of a memory card. + +Add "exit at end of successful download" automation feature. + +When an image's download is skipped, the thumbnail is now lightened. + +Show a missing image icon if the thumbnail cannot be displayed for some reason. +(See bug #369640 for why thumbnail images from certain RAW files are not +displayed). + +Resize main window when an image device is inserted -- it now expands to show +each device that is inserted. + +Do not proceed with download if there is an error in the image rename or +download subfolder preferences. Instead, indicate a download error. + +Allow version 0.1.1 of pyexiv2 to be used (an older version of the library code +that is used to get information on the images, found in distributions like +Ubuntu 8.04 Hardy Heron). + +In cases where image rename or download subfolder preferences are invalid, +more helpful information is printed to the console output. + +Bug fix: better handle automated shortening Canon names like 'Canon 5D Mark II'. +It is now shortened to '5DMkII' instead of merely '5D'. + +Bug fix: reenable example of image renaming and subfolder name generation by +using first image from the first available download device. This was +inadvertently disabled in an earlier beta. + +Bug fix: make default download subfolder YYYY/YYYYMMDD again. It was +inadvertently set to DDMMYYYY/YYYYMMDD in beta 6. + +Bug fix: don't change download button label to "pause" when "Start downloading +on program startup" is set to true. + +Bug fix: implement code to warn / give error about missing backup devices. + +Bug fix: reset progress bar after completion of successful download. + +Fix bug #317404 when clearing completed downloads. + + + +Version 0.0.8 beta 7 +-------------------- + +2009-04-07 + +Added serial number metadata option for select Nikon, Canon, Olympus, Fuji, +Panasonic, and Kodak cameras. + +Added shutter count metadata option for select Nikon cameras, e.g. Nikon D300, +D3 etc. + +Add owner name metadata option for select Canon cameras, e.g. 5D Mk II etc. + + +Version 0.0.8 beta 6 +-------------------- + +2009-03-31 + +Add YYYY-MM-DD and YY-MM-DD options in date time renaming, suggested by +Andreas F.X. Siegert and Paul Gear. + +Fix bug #352242 where image has no metadata. + +Handle images with corrupt metadata more gracefully. + + +Version 0.0.8 beta 5 +-------------------- + +2009-03-30 + +Reduce console output. + + +Version 0.0.8 beta 4 +-------------------- + +2009-03-25 + +Updated Ubuntu package. + +Version 0.0.8 beta 3 +-------------------- + +2009-03-25 + +Updated Ubuntu package. + + +Version 0.0.8 beta 2 +-------------------- + +2009-03-25 + +First Ububtu package. + +Rename tarball package to suit package name. + +Updated README. + +Version 0.0.8 beta 1 +-------------------- + +2009-03-20 + +Make file renaming thread safe, fixing a long-standing (if difficult to +activate) bug. + +Implement add unique identifier when file name is not unique. + +Added "Report a Problem", "Get Help Online", "Make a Donation" to Help menu. + +Implemented "Clear completed downloads" menu item. + +Download images in order they were taken (checked by time they modified). + +Fixed bug where choosing text as the first item in a download subfolder caused a +crash. + +Fixed bug where date and time choices based on when image is downloaded caused a +crash. + +Initial code to show error message when image renaming preferences have an +error. + +Fixed bug where some invalid preferences were not being caught. + +Run default python, not one specified in env, as per recommendations in Debian +Python Policy. + +Remove initial period from filename extension when generating a subfolder name +(or else the folder will be hidden). + +Check to see if metadata is essential to generate image names is now more +robust. + +Remove list control from preferences, reverting to normal tabbed preferences, +as the window was becoming too wide. + +Show notifcations via libnotify. + +Error and warning icons can now be clicked on to open log window. + +Finally, last but certainly not least--implemented sequence number and sequence +letter generation: + * session sequence number + * sequence letter +Coming soon: + * downloads today sequence number + * subfolder sequence number + * stored sequence number + + +Version 0.0.7 +------------- + +2009-01-13 + +Implemented option for automatic detection of Portal Storage Devices. + +Version 0.0.6 +------------- + +2009-01-11 + +Fixed extremely annoying bug where memory cards could not be unmounted. + +Made sample image selection for preferences more robust. + +Added license details to about dialog. + +Fix bug where image rename preferences entry boxes vertically expanded, looking +very ugly indeed. + +Wrap new filename in image rename preferences when it becomes too long. + +Make default download folder selection more robust. + +Remove sequence number and sequence letter from list of choices for image rename +(not yet implemented). + +Bug #314825: fix by not calling gnomevfs.get_local_path_from_uri() unless +strictly necessary. + +Version 0.0.5 +------------- + +2009-01-09 + +Implement auto download on device insertion, and auto download on program +startup. + +Increase default width of preferences dialog box. + +Add vertical scrollbar to image rename preferences. + +Fixes for bugs #313463 & #313462. + +Version 0.0.4 +------------- + +2009-01-06 + +Bug #314284: Implement backup functionality. + +Bug #314285: Insert debugging code to help determine the cause of this bug. + +Version 0.0.3 +------------- + +2009-01-03 + +Bug #313398: Fix bug where application needed to be restarted for new +preferences to take effect. + +Added setup.py installer. + +Version 0.0.2 +------------- + +Dependencies: +Pyexiv 0.1.2 + +Updated metadata code to reflect changes in pyexiv library. + +Version 0.0.1 +------------- + +Initial release. diff --git a/rapid/INSTALL b/rapid/INSTALL new file mode 100644 index 0000000..27f9b07 --- /dev/null +++ b/rapid/INSTALL @@ -0,0 +1,36 @@ +Rapid Photo Downloader depends on the following software: + +- GNOME 2.18 +- GTK+ 2.10 +- Python 2.5 +- pygtk 2.10 +- python-gconf 2.18 +- python-glade2 2.10 +- gnome-python 2.10 +- libexiv2 0.15 +- pyexiv2 0.1.1 + +To run Rapid Photo Downloader you will need all the software mentioned above. To +start from a fairly basic system, I suggest the following: + +1. Install the required gnome packages from your linux distribution's package + repositories. On a recent linux distribution, expect all to be available for + easy download and installation. If you already use gnome, most of the + packages will already be installed. Do confirm that python-gconf, + python-glade2, and gnome-python are installed, because they + may not be quite so common in a base system. + +2. Install pyexiv2. You can probably do that using your distributions's package + repositories (look for python-pyexiv2). But if not, there are instructions + here: + + http://tilloy.net/dev/pyexiv2/developers.htm + +3. Install this application from the tarball. You probably need to be the + super user (root) to be able to do this: + + sudo python setup.py install + + If you get an error saying 'Error while running msgfmt', you will need to + install the gettext package on your system, which contains the msgfmt + program. diff --git a/rapid/TODO b/rapid/TODO new file mode 100644 index 0000000..5465850 --- /dev/null +++ b/rapid/TODO @@ -0,0 +1,26 @@ +For major release (0.10.0): +=========================== + +* sequencing: + - allow generation of unique sequences based on date time for last 1 - n days, via menu + +* download profiles (combinations of subfolder and image renaming preferences) +* better handle preference changes while downloads are occurring +* handle unexpected media removal, disk full, all kinds of write errors +* indicate different levels of error better in log window +* sum amount of images to be downloaded, and how much free space on the file system +* check download locations and sources still valid when starting the application +* rework checkPrefsForValidity() to account for multiple subfolder problems + +For future releases: +==================== + +* Better application icon -- help needed! +* Get more metadata + - lens +* User defined camera model mapping +* Job codes +* use python's high performance deque to improve idletube + + + diff --git a/rapid/ValidatedEntry.py b/rapid/ValidatedEntry.py new file mode 100644 index 0000000..cb453f4 --- /dev/null +++ b/rapid/ValidatedEntry.py @@ -0,0 +1,383 @@ +# Copyright (c) 2006, Daniel J. Popowich +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation files +# (the "Software"), to deal in the Software without restriction, +# including without limitation the rights to use, copy, modify, merge, +# publish, distribute, sublicense, and/or sell copies of the Software, +# and to permit persons to whom the Software is furnished to do so, +# subject to the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +# Send bug reports and contributions to: +# +# dpopowich AT astro dot umass dot edu +# + +''' +ValidatedEntry.py + +Provides ValidatedEntry, a subclass of gtk.Entry which validates +input. + +Usage: create an instance of ValidatedEntry, specifying the function +to validate input. E.g.: + + : def money(text): + : "validate input to be monetary value" + : ... + : + : money_entry = ValidatedEntry(money) + +Validation functions must accept one argument, the text to be +validated, and must return one of: + + 1: the input is valid. + 0: the input is invalid and should not be displayed. + -1: the input is partially valid and will be displayed (and by + default with a different background color). + +Three module-level variables are defined for the convenience of +validation function writers: VALID (1), INVALID (0), PARTIAL (-1). + +There is one public method, isvalid(), which will return True if the +current text is valid. + +Note: care should be taken when implementing validation functions to +allow empty strings to be VALID or at least PARTIAL. An empty string +should never be INVALID. + +Note: the hooks for calling the validation function are implemented by +connecting the object to handlers for the gtk.Editable "insert-text" +and "delete-text" signals. These handlers are connected to instances +in the constructor, so will, by default, be called before other +handlers connected to the widgets for "*-text" signals. When input is +INVALID, stop_emission() is called, so later handlers for "*-text" +signals will not be called. + +See the doc string for ValidatedEntry.__init__ for more details. + +''' + +import pygtk +pygtk.require('2.0') + +import gtk +import gtk.gdk + +if gtk.gtk_version < (2, 8): + import warnings + + msg ='''This module was developed and tested with version 2.8.9 of gtk. +You are using version %d.%d.%d. Your milage may vary''' % gtk.gtk_version + warnings.warn(msg) + +# major, minor, patch +version = 1, 0, 4 + +PARTIAL, INVALID, VALID = range(-1,2) + +class ValidatedEntry(gtk.Entry): + + white = gtk.gdk.color_parse('white') + yellow = gtk.gdk.color_parse('yellow') + + def __init__(self, valid_func, + max=0, + use_bg=True, valid_bg=white, partial_bg=yellow, + error_func=None): + ''' + Create instance of validating gtk.Entry. + + valid_func: the function to validate input. See module doc + string for details. + + max: passed to gtk.Entry constructor. (default: 0) + + use_bg: if True (the default) set the base color of the + widget to indicate validity; see valid_bg and partial_bg. + + valid_bg: a gtk.gdk.Color; the base color of the widget when + the input is valid. (default: white) + + partial_bg: a gtk.gdk.Color; the base color of the widget when + the input is partially valid. (default: yellow) + + error_func: a function to call (with no arguments) when + valid_func returns INVALID. If None (the default) + the default action will be to emit a short beep. + ''' + + assert valid_func('') != INVALID, 'valid_func cannot return INVALID for an empty string' + + gtk.Entry.__init__(self, max) + + self.__valid_func = valid_func + self.__use_bg = use_bg + self.__valid_bg = valid_bg + self.__partial_bg = partial_bg + self.__error_func = (error_func or + gtk.gdk.display_get_default().beep) + + self.connect('insert-text', self.__insert_text_cb) + self.connect('delete-text', self.__delete_text_cb) + + # bootstrap with an empty string (so the box will appear with + # the partial_bg if an empty string is PARTIAL) + self.insert_text('') + + def isvalid(self): + return self.__isvalid + + def __insert_text_cb(self, entry, text, length, position): + 'callback for "insert-text" signal' + + # generate what the new text will be + text = text[:length] + pos = self.get_position() + old = self.get_text() + new = old[:pos] + text + old[pos:] + + # validate the new text + self.__validate(new, 'insert-text') + + def __delete_text_cb(self, entry, start, end): + 'callback for "delete-text" signal' + + # generate what the new text will be + old = self.get_text() + new = old[:start] + old[end:] + + # validate the new text + self.__validate(new, 'delete-text') + + def __validate(self, text, signal): + 'calls the user-provided validation function' + + # validate + r = self.__valid_func(text) + if r == VALID: + self.__isvalid = True + if self.__use_bg: + self.modify_base(gtk.STATE_NORMAL, self.__valid_bg) + elif r == PARTIAL: + self.__isvalid = False + if self.__use_bg: + self.modify_base(gtk.STATE_NORMAL, self.__partial_bg) + else: + # don't set self.__isvalid: since we're not displaying the + # new value, the validity should be whatever it was before + self.stop_emission(signal) + self.__error_func() + + +###################################################################### +# +# Sample validation functions to use with ValidatedEntry +# +###################################################################### + +import re + + +# STRING (non-empty after stripping) +def v_nonemptystring(value): + ''' + VALID: non-empty string after stripping whitespace + PARTAL: empty or all whitespace + INVALID: N/A + ''' + if value.strip(): + return VALID + return PARTIAL + +# INT +def v_int(value): + ''' + VALID: any postive or negative integer + PARTAL: empty or leading "-" + INVALID: non-numeral + ''' + v = value.strip() + if not v or v == '-': + return PARTIAL + try: + int(value) + return VALID + except: + return INVALID + +# FLOAT +def v_float(value): + ''' + VALID: any postive or negative floating point + PARTAL: empty or leading "-", "." + INVALID: non-numeral + ''' + v = value.strip() + if not v or v in ('-', '.', '-.'): + return PARTIAL + try: + float(value) + return VALID + except: + return INVALID + + +# ISBN +_isbnpartial = re.compile('[0-9]{0,9}[0-9xX]?$') +def v_isbn(v): + + '''Validate ISBN input. + + From the isbn manual, section 4.4: + + The check digit is the last digit of an ISBN. It is calculated on + a modulus 11 with weights 10-2, using X in lieu of 10 where ten + would occur as a check digit. This means that each of the first + nine digits of the ISBN -- excluding the check digit itself -- is + multiplied by a number ranging from 10 to 2 and that the resulting + sum of the products, plus the check digit, must be divisible by 11 + without a remainder.''' + + + if _isbnpartial.match(v): + # isbn is ten characters in length + if len(v) < 10: + return PARTIAL + + s = 0 + + for i, c in enumerate(v): + s += (c in 'xX' and 10 or int(c)) * (10 - i) + + if s % 11 == 0: + return VALID + + return INVALID + +# MONEY +# re for (possibly negative) money +_money_re = re.compile('-?\d*(\.\d{1,2})?$') +# validation function for money +def v_money(value): + ''' + VALID: any postive or negative floating point with at most two + digits after the decimal point. + PARTAL: empty or leading "-", "." + INVALID: non-numeral or more than two digits after the decimal + point. + ''' + if not value or value == '-' or value[-1] == '.': + return PARTIAL + + if _money_re.match(value): + return VALID + + return INVALID + +# PHONE +# the characters in a phone number +_phonechars = re.compile('[- 0-9]*$') +# valid phone number: [AC +]EXT-LINE +_phone = re.compile('([2-9][0-8][0-9]\s+)?[2-9][0-9]{2}-[0-9]{4}$') +def v_phone(value): + ''' + VALID: any phone number of the form: EXT-LINE -or- AC EXT-LINE. + PARTAL: any characters that make up a valid #. + INVALID: characters that are not used in a phone #. + ''' + if _phone.match(value): + return VALID + if _phonechars.match(value): + return PARTIAL + return INVALID + +def empty_valid(vfunc): + + ''' + empty_valid is a factory function returning a validation function. + All of the validation functions in this module return PARTIAL for + empty strings which, in effect, forces non-empty input. There may + be a case where, e.g., you want money input to be optional, but + v_money will not consider empty input VALID. Instead of writing + another validation function you can instead use empty_valid(). By + wrapping a validation function with empty_valid(), input (after + stripping), if empty, will be considered VALID. E.g.: + + ventry = ValidatedEntry(empty_valid(v_money)) + + It is recommended that all your validation functions treat empty + input as PARTIAL, for consistency across all validation functions + and for use with empty_valid(). + ''' + + def validate(value): + if not value.strip(): + return VALID + return vfunc(value) + + return validate + + +def bounded(vfunc, conv, minv=None, maxv=None): + + ''' + bounded is a factory function returning a validation function + providing bounded input. E.g., you may want an entry that accepts + integers, but within a range, say, a score on a test graded in + whole numbers from 0 to 100: + + score_entry = ValidatedEntry(bounded(v_int, int, 0, 100)) + + Arguments: + + vfunc: A validation function. + conv: A callable that accepts a string argument (the text in + the entry) and returns a value to be compared to minv + and maxv. + minv: None or a value of the same type returned by conv. If + None, there is no minimum value enforced. If a value, + it will be the minimum value considered VALID. + maxv: None or a value of the same type returned by conv. If + None, there is no maximum value enforced. If a value, + it will be the maximum value considered VALID. + + One or both of minv/maxv must be specified. + + The function returned will call vfunc on entry input and if vfunc + returns VALID, the input will be converted by conv and compared to + minv/maxv. If the converted value is within the bounds of + minv/maxv then VALID will be returned, else PARTIAL will be + returned. + + ''' + + assert minv is not None or maxv is not None, \ + 'One of minv/maxv must be specified' + + def F(value): + + r = vfunc(value) + if r == VALID: + v = conv(value) + if minv is not None and v < minv: + return PARTIAL + if maxv is not None and v > maxv: + return PARTIAL + return r + + return F + + diff --git a/rapid/__init__.py b/rapid/__init__.py new file mode 100644 index 0000000..792d600 --- /dev/null +++ b/rapid/__init__.py @@ -0,0 +1 @@ +# diff --git a/rapid/common.py b/rapid/common.py new file mode 100644 index 0000000..d687049 --- /dev/null +++ b/rapid/common.py @@ -0,0 +1,181 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007-09 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os +import sys +import gc +import distutils.version +import gtk.gdk as gdk + +import config + +import locale +import gettext + +class Configi18n: + """ Setup translation + + Adapated from code example of Mark Mruss http://www.learningpython.com. + Unlike his example, this code uses a local locale directory only if the environment + variable LOCALEDIR has been set to some or other value. + """ + + # Do not put this code block in __init__, because it needs to be run only once + + # if the evironment value 'LOCAELDIR' is set, then use this as the source of translation data + # otherwise, rely on the system-wide data + locale_path = os.environ.get('LOCALEDIR', None) + + # Init the list of languages to support + langs = [] + #Check the default locale + lc, encoding = locale.getdefaultlocale() + if (lc): + #If we have a default, it's the first in the list + langs = [lc] + # Now let's get all of the supported languages on the system + language = os.environ.get('LANGUAGE', None) + if (language): + # langage comes back something like en_CA:en_US:en_GB:en + langs += language.split(":") + + # add on to the back of the list the translations that we know that we have, our defaults + langs += ["en_US"] + + # Now langs is a list of all of the languages that we are going + # to try to use. First we check the default, then what the system + # told us, and finally the 'known' list + + gettext.bindtextdomain(config.APP_NAME, locale_path) + gettext.textdomain(config.APP_NAME) + # Get the language to use + lang = gettext.translation(config.APP_NAME, locale_path, languages=langs, fallback = True) + # Install the language, map _() (which we marked our + # strings to translate with) to self.lang.gettext() which will + # translate them. + _ = lang.gettext + + +def pythonifyVersion(v): + """ makes version number a version number in distutils sense""" + return distutils.version.StrictVersion(v.replace( '~','')) + +def getFullProgramName(): + """ return the full name of the process running """ + return os.path.basename(sys.argv[0]) + +def getProgramName(): + """ return the name of the process running, removing the .py extension if it exists """ + programName = getFullProgramName() + if programName.find('.py') > 0: + programName = programName[:programName.find('.py')] + return programName + +def splitDirectories(directories): + """ split directories specified in string into a list """ + if directories.find(',') > 0: + d = directories.split(',') + else: + d = directories.split() + directories = [] + for i in d: + directories.append(i.strip()) + return directories + + + +def getFullPath(path): + """ make path relative to home directory if not an absolute path """ + if os.path.isabs(path): + return path + else: + return os.path.join(os.path.expanduser('~'), path) + + +def escape(s): + """ + Replace special characters by SGML entities. + """ + entities = ("&&", "<<", ">>") + for e in entities: + s = s.replace(e[0], e[1:]) + return s + +def formatSizeForUser(bytes, zeroString="", withDecimals=True, kbOnly=False): + """Format an int containing the number of bytes into a string suitable for + printing out to the user. zeroString is the string to use if bytes == 0. + source: https://develop.participatoryculture.org/trac/democracy/browser/trunk/tv/portable/util.py?rev=3993 + + """ + if bytes > (1 << 30) and not kbOnly: + value = (bytes / (1024.0 * 1024.0 * 1024.0)) + if withDecimals: + format = "%1.1fGB" + else: + format = "%dGB" + elif bytes > (1 << 20) and not kbOnly: + value = (bytes / (1024.0 * 1024.0)) + if withDecimals: + format = "%1.1fMB" + else: + format = "%dMB" + elif bytes > (1 << 10): + value = (bytes / 1024.0) + if withDecimals: + format = "%1.1fKB" + else: + format = "%dKB" + elif bytes > 1: + value = bytes + if withDecimals: + format = "%1.1fB" + else: + format = "%dB" + else: + return zeroString + return format % value + +def scale2pixbuf(width_max, height_max, pixbuf, return_size=False): + """ + Scale to width_max and height_max. + Keep aspect ratio. + Code adapted from gthumpy, by guettli + """ + + width_orig = float(pixbuf.get_width()) + height_orig = float(pixbuf.get_height()) + if (width_orig / width_max) > (height_orig / height_max): + height = int((height_orig / width_orig) * width_max) + width = width_max + else: + width = int((width_orig / height_orig) * height_max) + height=height_max + + pixbuf = pixbuf.scale_simple(width, height, gdk.INTERP_BILINEAR) + gc.collect() # Tell Python to clean up the memory + if return_size: + return pixbuf, width_orig, height_orig + return pixbuf + + + +if __name__ == '__main__': + i = Configi18n() + _ = i._ + print _("hello world") diff --git a/rapid/config.py b/rapid/config.py new file mode 100644 index 0000000..2e59841 --- /dev/null +++ b/rapid/config.py @@ -0,0 +1,58 @@ +# -*- coding: latin1 -*- +### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +version = '0.0.10' + +GCONF_KEY="/apps/rapid-photo-downloader" +GLADE_FILE = "glade3/rapid.glade" + +DBUS_NAME = "net.damonlynch.RapidPhotoDownloader" + +#i18n +APP_NAME = "rapid-photo-downloader" + +MEDIA_LOCATION = "/media" + +SKIP_DOWNLOAD = "skip download" +ADD_UNIQUE_IDENTIFIER = "add unique identifier" + +REPORT_WARNING = "warning" +REPORT_ERROR = "error" +IGNORE = "ignore" + +DEFAULT_PHOTO_LOCATIONS = ['Pictures', 'Photos'] +DEFAULT_BACKUP_LOCATION = 'Pictures' + +MAX_NO_READERS = 20 + +RAW_FILE_EXTENSIONS = ['arw', 'dcr', 'cr2', 'crw', 'dng', 'mef', 'mos', 'mrw', + 'nef', 'orf', 'pef', 'raf', 'raw', 'sr2'] + +#exiv2 0.18.1 introduces support for Panasonic .RW2 files + +NON_RAW_IMAGE_FILE_EXTENSIONS = ['jpg', 'jpe', 'jpeg', 'tif', 'tiff'] + +CRITICAL_ERROR = 1 +SERIOUS_ERROR = 2 +WARNING = 3 + +MAX_LENGTH_DEVICE_NAME = 15 + +#logging - to be implemented +#LOGFILE_DIRECTORY = '.rapidPhotoDownloader' # relative to home directory +#MAX_LOGFILE_SIZE = 100 * 1024 # bytes +#MAX_LOGFILES = 5 diff --git a/rapid/glade3/image-missing.svg b/rapid/glade3/image-missing.svg new file mode 100644 index 0000000..4351feb --- /dev/null +++ b/rapid/glade3/image-missing.svg @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="48px" height="48px" id="svg1306" sodipodi:version="0.32" inkscape:version="0.45" sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/status" sodipodi:docname="image-missing.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape"> + <defs id="defs1308"> + <linearGradient inkscape:collect="always" id="linearGradient6346"> + <stop style="stop-color: rgb(85, 87, 83); stop-opacity: 1;" offset="0" id="stop6348"/> + <stop style="stop-color: rgb(46, 52, 54); stop-opacity: 1;" offset="1" id="stop6350"/> + </linearGradient> + <linearGradient inkscape:collect="always" id="linearGradient5060"> + <stop style="stop-color: black; stop-opacity: 1;" offset="0" id="stop5062"/> + <stop style="stop-color: black; stop-opacity: 0;" offset="1" id="stop5064"/> + </linearGradient> + <linearGradient id="linearGradient5048"> + <stop style="stop-color: black; stop-opacity: 0;" offset="0" id="stop5050"/> + <stop id="stop5056" offset="0.5" style="stop-color: black; stop-opacity: 1;"/> + <stop style="stop-color: black; stop-opacity: 0;" offset="1" id="stop5052"/> + </linearGradient> + <linearGradient inkscape:collect="always" id="linearGradient6431"> + <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop6433"/> + <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop6435"/> + </linearGradient> + <linearGradient inkscape:collect="always" id="linearGradient6390"> + <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop6392"/> + <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop6394"/> + </linearGradient> + <linearGradient id="linearGradient6374"> + <stop style="stop-color: rgb(85, 87, 83); stop-opacity: 1;" offset="0" id="stop6376"/> + <stop style="stop-color: rgb(136, 138, 133); stop-opacity: 1;" offset="1" id="stop6378"/> + </linearGradient> + <linearGradient id="linearGradient6366"> + <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop6368"/> + <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop6370"/> + </linearGradient> + <linearGradient id="linearGradient6327"> + <stop style="stop-color: rgb(136, 138, 133); stop-opacity: 1;" offset="0" id="stop6329"/> + <stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="1" id="stop6331"/> + </linearGradient> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient6327" id="linearGradient6333" x1="42.999424" y1="36.811924" x2="40.621296" y2="34.433796" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient6327" id="linearGradient6360" x1="61.18124" y1="137.97644" x2="20.420683" y2="2.6749926" gradientUnits="userSpaceOnUse"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient6366" id="linearGradient6372" x1="38.908649" y1="35.960426" x2="35.032925" y2="30.679369" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient6374" id="radialGradient6382" cx="39.437065" cy="34.33852" fx="39.437065" fy="34.33852" r="6" gradientTransform="matrix(0.1875, -1.05343, 0.718081, 0.127811, 7.82271, 71.0304)" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient6390" id="radialGradient6396" cx="20.236877" cy="25.043303" fx="20.236877" fy="25.043303" r="22" gradientTransform="matrix(0.940906, -0.20665, 0.109821, 0.50003, -1.55441, 13.2196)" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient6431" id="radialGradient6437" cx="40.179535" cy="34.080399" fx="40.179535" fy="34.080399" r="4.125" gradientTransform="matrix(1, 0, 0, 0.935606, 0, 2.30711)" gradientUnits="userSpaceOnUse"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient5060" id="radialGradient6909" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-0.0160648, 0, 0, 0.0741176, 11.6816, -1.17508)" cx="605.71429" cy="486.64789" fx="605.71429" fy="486.64789" r="117.14286"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient5060" id="radialGradient6912" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.104421, 0, 0, 0.0741176, -27.9305, -1.17508)" cx="605.71429" cy="486.64789" fx="605.71429" fy="486.64789" r="117.14286"/> + <linearGradient inkscape:collect="always" xlink:href="#linearGradient5048" id="linearGradient6915" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.0683432, 0, 0, 0.0741176, -6.20118, -1.17508)" x1="302.85715" y1="366.64789" x2="302.85715" y2="609.50507"/> + <radialGradient inkscape:collect="always" xlink:href="#linearGradient6346" id="radialGradient6352" cx="24.013514" cy="39.717846" fx="24.013514" fy="39.717846" r="20.013513" gradientTransform="matrix(2.00322, 0, 0, 1.45136, -24.0909, -22.3947)" gradientUnits="userSpaceOnUse"/> + </defs> + <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" inkscape:cx="50.321592" inkscape:cy="19.160509" inkscape:current-layer="layer1" showgrid="false" inkscape:grid-bbox="true" inkscape:document-units="px" fill="#fcaf3e" stroke="#555753" showguides="true" inkscape:guide-bbox="false" inkscape:window-width="895" inkscape:window-height="760" inkscape:window-x="208" inkscape:window-y="229" inkscape:showpageshadow="false" showborder="false" gridspacingx="0.5px" gridspacingy="0.5px" gridempspacing="2" inkscape:grid-points="false" gridtolerance="50" inkscape:object-paths="false"/> + <metadata id="metadata1311"> + <rdf:RDF> + <cc:Work rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> + <dc:title>Generic Image</dc:title> + <dc:creator> + <cc:Agent> + <dc:title>Lapo Calamandrei</dc:title> + </cc:Agent> + </dc:creator> + <dc:source>http://www.gnome.org</dc:source> + <dc:contributor> + <cc:Agent> + <dc:title>Jakub Steiner, Andreas Nilsson</dc:title> + </cc:Agent> + </dc:contributor> + <cc:license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/"/> + </cc:Work> + <cc:License rdf:about="http://creativecommons.org/licenses/GPL/2.0/"> + <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/> + <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/> + <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/> + <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/> + <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/> + <cc:requires rdf:resource="http://web.resource.org/cc/SourceCode"/> + </cc:License> + </rdf:RDF> + </metadata> + <g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer"> + <g id="g6917"> + <rect y="26" x="2" height="18" width="33" id="rect6057" style="overflow: visible; marker: none; opacity: 0.39196; color: rgb(0, 0, 0); fill: url(#linearGradient6915) rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline;"/> + <path sodipodi:nodetypes="ccscc" id="path6059" d="M 35,26.00062 C 35,26.00062 35,43.999627 35,43.999627 C 37.30962,44.01418 40.033409,43.272315 42.389531,42.027493 C 45.519106,40.37403 48.000002,37.833194 48,34.998965 C 48,30.030967 41.999197,26.000621 35,26.00062 z " style="overflow: visible; marker: none; opacity: 0.402062; color: rgb(0, 0, 0); fill: url(#radialGradient6912) rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline;"/> + <path style="overflow: visible; marker: none; opacity: 0.402062; color: rgb(0, 0, 0); fill: url(#radialGradient6909) rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline;" d="M 2,26.00062 C 2,26.00062 2,43.999627 2,43.999627 C 1.172704,44.03351 1.3577825e-06,39.966963 1.3577825e-06,34.998965 C 1.3577825e-06,30.030967 0.92320113,26.000621 2,26.00062 z " id="path6061" sodipodi:nodetypes="cccc"/> + </g> + <path style="fill: url(#linearGradient6360) rgb(0, 0, 0); fill-opacity: 1; stroke: rgb(136, 138, 133); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 2.767767,6.5 L 45.232237,6.5 C 45.93458,6.5 46.500004,7.0654241 46.500004,7.767767 L 46.5,30.5 C 46.5,31.202343 36.202343,40.5 35.5,40.5 L 2.767767,40.5 C 2.0654241,40.5 1.5,39.934576 1.5,39.232233 L 1.5,7.767767 C 1.5,7.0654241 2.0654241,6.5 2.767767,6.5 z " id="rect5350" sodipodi:nodetypes="ccccccccc"/> + <path style="fill: url(#radialGradient6352) rgb(0, 0, 0); fill-opacity: 1; stroke: rgb(136, 138, 133); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 4.9874617,9.5 L 43.039565,9.5 C 43.309619,9.5 43.527027,9.7276458 43.527027,10.010417 L 43.527027,33.989583 L 40.039565,37.5 L 4.9874617,37.5 C 4.7174079,37.5 4.5,37.272354 4.5,36.989583 L 4.5,10.010417 C 4.5,9.7276458 4.7174079,9.5 4.9874617,9.5 z " id="rect2063" sodipodi:nodetypes="ccccccccc"/> + <path style="opacity: 0.172414; fill: url(#linearGradient6372) rgb(0, 0, 0); fill-opacity: 1; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 14.78125,40 L 35.40625,40 C 35.41645,39.995518 35.423208,39.996022 35.46875,39.96875 C 35.559833,39.914206 35.707858,39.809986 35.875,39.6875 C 36.209283,39.442528 36.659837,39.093896 37.1875,38.65625 C 38.242827,37.780957 39.61066,36.608491 40.9375,35.40625 C 42.26434,34.204009 43.563777,32.96157 44.53125,32 C 45.014987,31.519215 45.417906,31.118778 45.6875,30.8125 C 45.822297,30.659361 45.910802,30.519277 45.96875,30.4375 C 45.983237,30.417056 45.991685,30.419536 46,30.40625 L 46,13.78125 L 14.78125,40 z " id="path6364" sodipodi:nodetypes="ccsssssssccc"/> + <path style="fill: none; fill-opacity: 1; stroke: rgb(255, 255, 255); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 2.78125,7.5 C 2.6253137,7.5 2.5,7.6253137 2.5,7.78125 L 2.5,39.21875 C 2.5,39.374686 2.6253136,39.5 2.78125,39.5 L 37.28125,39.5 C 40.921301,36.704635 42.365769,35.606734 45.5,32.25 L 45.5,7.78125 C 45.5,7.6253155 45.374683,7.5 45.21875,7.5 L 2.78125,7.5 z " id="path6351" sodipodi:nodetypes="ccccccccc"/> + <path style="fill: url(#linearGradient6333) rgb(0, 0, 0); fill-rule: evenodd; stroke: url(#radialGradient6382) rgb(0, 0, 0); stroke-width: 1px; stroke-linecap: butt; stroke-linejoin: round; stroke-opacity: 1; fill-opacity: 1;" d="M 46.5,30.5 C 46.5,35.5 40.5,40.5 35.5,40.5 C 35.5,40.5 39.932134,38.33738 39.5,33.5 C 43.879686,33.916135 46.5,30.5 46.5,30.5 z " id="path6322" sodipodi:nodetypes="cccc"/> + <path style="fill: url(#radialGradient6437) rgb(0, 0, 0); fill-opacity: 1; fill-rule: evenodd; stroke: none; stroke-width: 1px; stroke-linecap: butt; stroke-linejoin: round; stroke-opacity: 1; opacity: 0.732759;" d="M 45.71875 31.96875 C 44.577589 32.932531 42.679856 34.08934 40.03125 34.03125 C 40.059733 36.774444 38.699098 38.58751 37.46875 39.6875 C 38.953141 38.706251 40.825166 37.371805 41.03125 35.03125 C 43.192381 35.027997 44.619214 33.310655 45.6875 32.03125 C 45.693038 32.009581 45.713422 31.990426 45.71875 31.96875 z " id="path6339"/> + <path style="fill: url(#radialGradient6396) rgb(0, 0, 0); fill-opacity: 1; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1; opacity: 0.344828;" d="M 2.78125,7 C 2.3536576,7 2,7.3536576 2,7.78125 L 2,31.09375 C 14.714701,22.184679 34.055102,15.625228 46,19.3125 L 46,7.78125 C 46,7.3536585 45.64634,7 45.21875,7 L 2.78125,7 z " id="path6384" sodipodi:nodetypes="ccccccc"/> + <path sodipodi:type="inkscape:offset" inkscape:radius="-1" inkscape:original="M 2.78125 6.5 C 2.0789071 6.5 1.5 7.0789071 1.5 7.78125 L 1.5 39.21875 C 1.5 39.921093 2.0789071 40.5 2.78125 40.5 L 35.5 40.5 C 40.5 40.5 46.5 35.5 46.5 30.5 L 46.5 7.78125 C 46.5 7.0789071 45.921091 6.5 45.21875 6.5 L 2.78125 6.5 z " style="fill: none; fill-opacity: 1; stroke: rgb(255, 255, 255); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1; opacity: 0.418103;" id="path6427" d="M 2.78125,7.5 C 2.628408,7.5 2.5,7.628408 2.5,7.78125 L 2.5,39.21875 C 2.5,39.371592 2.6284079,39.5 2.78125,39.5 L 35.5,39.5 C 37.666667,39.5 40.249358,38.362698 42.21875,36.625 C 44.188142,34.887302 45.5,32.6 45.5,30.5 L 45.5,7.78125 C 45.5,7.6284098 45.371589,7.5 45.21875,7.5 L 2.78125,7.5 z "/> + </g> +</svg>
\ No newline at end of file diff --git a/rapid/glade3/rapid-photo-downloader-about.png b/rapid/glade3/rapid-photo-downloader-about.png Binary files differnew file mode 100644 index 0000000..0aefb1d --- /dev/null +++ b/rapid/glade3/rapid-photo-downloader-about.png diff --git a/rapid/glade3/rapid.glade b/rapid/glade3/rapid.glade new file mode 100644 index 0000000..be01fa4 --- /dev/null +++ b/rapid/glade3/rapid.glade @@ -0,0 +1,2716 @@ +<?xml version="1.0"?> +<glade-interface> + <!-- interface-requires gtk+ 2.16 --> + <!-- interface-naming-policy toplevel-contextual --> + <widget class="GtkDialog" id="preferencesdialog"> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="border_width">5</property> + <property name="title" translatable="yes">Preferences: Rapid Photo Downloader</property> + <property name="modal">True</property> + <property name="window_position">center-on-parent</property> + <property name="default_height">500</property> + <property name="icon">rapid-photo-downloader-about.png</property> + <property name="type_hint">dialog</property> + <property name="has_separator">False</property> + <signal name="destroy" handler="on_preferencesdialog_destroy"/> + <signal name="response" handler="on_response"/> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox2"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkScrolledWindow" id="scrolled_window"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="resize_mode">queue</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <property name="shadow_type">in</property> + <child> + <widget class="GtkTreeView" id="treeview"> + <property name="width_request">100</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="headers_visible">False</property> + <signal name="cursor_changed" handler="on_treeview_cursor_changed"/> + </widget> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkNotebook" id="notebook"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_border">False</property> + <child> + <widget class="GtkVBox" id="folder_tab"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox6"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Download Folder</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox9"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label16"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="download_folder_table"> + <property name="visible">True</property> + <property name="n_rows">7</property> + <property name="n_columns">3</property> + <child> + <widget class="GtkVBox" id="subfolder_vbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="y_padding">12</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="example_download_path_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><i>Example: /home/user/photos</i></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label8"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Download Subfolders</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="lblPhotos1"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Download folder:</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label7"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">Choose the download folder. Subfolders for the downloaded photos will be automatically created in this folder using the structure specified below.</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label5"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Download Folder</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="subfolder_warning_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="wrap">True</property> + <property name="wrap_mode">word-char</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label23"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="menu_label">Download Folders</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="download_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Download Folder</property> + </widget> + <packing> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="rename_tab"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox5"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image3"> + <property name="visible">True</property> + <property name="stock">gtk-convert</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Image Rename</span> </property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator2"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox12"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label24"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="rename_vbox"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label42"> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Image Rename</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkScrolledWindow" id="rename_scrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <property name="window_placement_set">True</property> + <child> + <widget class="GtkViewport" id="viewport2"> + <property name="visible">True</property> + <property name="resize_mode">queue</property> + <property name="shadow_type">none</property> + <child> + <widget class="GtkVBox" id="rename_table_vbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="rename_example_table"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">3</property> + <child> + <widget class="GtkLabel" id="label17"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label15"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options"></property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="new_name_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes">translators please ignore this</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="original_name_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">translators please ignore this</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label21"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="label" translatable="yes"><i>New:</i></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label20"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><i>Original:</i></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label14"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Example</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="y_padding">12</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label25"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="menu_label">Rename</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="rename_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Image Rename</property> + </widget> + <packing> + <property name="position">1</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="rename_options_tab"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox14"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox18"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image7"> + <property name="visible">True</property> + <property name="icon_name">input-keyboard</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Rename Options</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator4"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox12"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label29"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes"><b>Sequence numbers</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox21"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label46"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox13"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label47"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Specify the time in 24 hour format at which the <i>Downloads today</i> sequence number should be reset.</property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox23"> + <property name="visible">True</property> + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label49"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Day start:</property> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label51"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Downloads today:</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label52"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Stored number:</property> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label54"> + <property name="visible">True</property> + <property name="xpad">6</property> + <property name="label" translatable="yes"> </property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="sequence_vbox"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkHBox" id="hbox22"> + <property name="visible">True</property> + <child> + <widget class="GtkSpinButton" id="hour_spinbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="width_chars">2</property> + <property name="xalign">1</property> + <property name="truncate_multiline">True</property> + <property name="adjustment">0 0 23 1 10 0</property> + <property name="numeric">True</property> + <signal name="value_changed" handler="on_hour_spinbutton_value_changed"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label50"> + <property name="visible">True</property> + <property name="label" translatable="yes">:</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkSpinButton" id="minute_spinbutton"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="width_chars">2</property> + <property name="xalign">1</property> + <property name="truncate_multiline">True</property> + <property name="adjustment">0 0 59 1 10 0</property> + <property name="numeric">True</property> + <signal name="value_changed" handler="on_minute_spinbutton_value_changed"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label53"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"> hh:mm</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label48"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label44"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes"><b>Compatibility with Other Operating Systems</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox16"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label32"> + <property name="visible">True</property> + <property name="xpad">12</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="compatibility_table"> + <property name="visible">True</property> + <property name="n_rows">9</property> + <property name="n_columns">2</property> + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Specify whether image and folder names should have any characters removed that are not allowed by other operating systems.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="strip_characters_checkbutton"> + <property name="label" translatable="yes">Strip incompatible characters</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_strip_characters_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label33"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">12</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="rename_options_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Rename Options</property> + </widget> + <packing> + <property name="position">2</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="device_tab"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image6"> + <property name="visible">True</property> + <property name="icon_name">media-flash</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label22"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Image Devices</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator5"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label41"> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes"><b>Image Devices</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label18"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes">Image devices are devices from which to download photos, such as cameras, memory cards or Portable Storage Devices. + +You can download photos from multiple image devices simultaneously. + +<i>If downloading directly from your camera works poorly or not at all, try setting it to PTP mode. If that is not possible, consider using a card reader.</i></property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox14"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label26"> + <property name="visible">True</property> + <property name="xpad">3</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="devices_table"> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="row_spacing">3</property> + <child> + <widget class="GtkCheckButton" id="autodetect_psd_checkbutton"> + <property name="label" translatable="yes">Automatically detect Portable Storage Devices</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_autodetect_psd_checkbutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="autodetect_device_checkbutton"> + <property name="label" translatable="yes">Automatically detect image devices</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_autodetect_device_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="autodetect_image_devices_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">6</property> + <property name="label" translatable="yes">If you enable automatic detection of Portable Storage Devices, the entire device will be scanned for images. On large devices, this could take some time.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label28"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox15"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkTable" id="devices2_table"> + <property name="visible">True</property> + <property name="n_rows">2</property> + <property name="n_columns">2</property> + <child> + <widget class="GtkLabel" id="device_location_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes">Image location:</property> + </widget> + <packing> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_SHRINK</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="device_location_explanation_label"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">If you disable automatic detection, choose the exact location of the images.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkLabel" id="label30"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">3</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="device_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Image Devices</property> + </widget> + <packing> + <property name="position">3</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="backup_tab"> + <property name="visible">True</property> + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox7"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image8"> + <property name="visible">True</property> + <property name="icon_name">drive-removable-media</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label27"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Backup</span> </property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator6"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox9"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label43"> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes"><b>Backup</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox20"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label38"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="backup_table"> + <property name="visible">True</property> + <property name="n_rows">8</property> + <property name="n_columns">4</property> + <child> + <widget class="GtkLabel" id="backup_location_explanation_label"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">If you disable automatic detection, choose the exact backup location.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">4</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="auto_detect_backup_checkbutton"> + <property name="label" translatable="yes">Automatically detect backup devices</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_auto_detect_backup_checkbutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">4</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">You can have your photos backed up to multiple locations as they are downloaded, e.g. external hard drives.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="right_attach">4</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="backup_checkbutton"> + <property name="label" translatable="yes">Backup photos when downloading</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_backup_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">4</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="backup_identifier_explanation_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">6</property> + <property name="label" translatable="yes">Specify the folder in which backups are stored on the device. + +<i>Note: this will also be used to determine whether or not the device is used for backups. For each device you wish to use for backing up to, create a folder in it with this name.</i></property> + <property name="use_markup">True</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">4</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="backup_location_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Backup location:</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">3</property> + <property name="top_attach">7</property> + <property name="bottom_attach">8</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="backup_identifier_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes">Backup folder name:</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">6</property> + <property name="bottom_attach">5</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options"></property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="backup_example_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="ypad">6</property> + <property name="label" translatable="yes"><i>Example:</i></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">2</property> + <property name="right_attach">3</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="x_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="example_backup_path_label"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="yalign">0</property> + <property name="ypad">6</property> + <property name="label" translatable="yes"><i>/media/externaldrive/Photos</i></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <widget class="GtkEntry" id="backup_identifier_entry"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <signal name="changed" handler="on_backup_identifier_entry_changed"/> + </widget> + <packing> + <property name="left_attach">3</property> + <property name="right_attach">4</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="y_options"></property> + <property name="y_padding">12</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label39"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="backup_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Backup</property> + </widget> + <packing> + <property name="position">4</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="automation_tab"> + <property name="visible">True</property> + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox10"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-execute</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label31"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Automation</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator7"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox11"> + <property name="visible">True</property> + <child> + <widget class="GtkLabel" id="label45"> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes"><b>Program Automation</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox17"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkLabel" id="label34"/> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="automation_table"> + <property name="visible">True</property> + <property name="n_rows">7</property> + <property name="n_columns">3</property> + <child> + <widget class="GtkCheckButton" id="auto_unmount_checkbutton"> + <property name="label" translatable="yes">Unmount ("eject") image device upon download completion</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_auto_unmount_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="auto_startup_checkbutton"> + <property name="label" translatable="yes">Start downloading at program startup</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_auto_startup_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">3</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="auto_insertion_checkbutton"> + <property name="label" translatable="yes">Start downloading upon image device insertion</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_auto_insertion_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="auto_exit_checkbutton"> + <property name="label" translatable="yes">Exit program after completion of successful download</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_auto_exit_checkbutton_toggled"/> + </widget> + <packing> + <property name="right_attach">3</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="padding">24</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label35"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">5</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="automation_label"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Automation</property> + </widget> + <packing> + <property name="position">5</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="error_tab"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkVBox" id="vbox8"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="hbox13"> + <property name="visible">True</property> + <property name="spacing">6</property> + <child> + <widget class="GtkImage" id="image9"> + <property name="visible">True</property> + <property name="stock">gtk-dialog-error</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label40"> + <property name="visible">True</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Error Handling</span></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator9"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox19"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkLabel" id="label36"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkTable" id="error_table"> + <property name="visible">True</property> + <property name="n_rows">14</property> + <property name="n_columns">2</property> + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes"> </property> + </widget> + <packing> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">GTK_FILL</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label12"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="label" translatable="yes"><b>Image Name Conflicts</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="backup_ignore_radiobutton"> + <property name="label" translatable="yes">Ignore</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">backup_error_radiobutton</property> + <signal name="toggled" handler="on_backup_ignore_radiobutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">13</property> + <property name="bottom_attach">14</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="backup_warning_radiobutton"> + <property name="label" translatable="yes">Report a warning</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">backup_error_radiobutton</property> + <signal name="toggled" handler="on_backup_warning_radiobutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">12</property> + <property name="bottom_attach">13</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="backup_error_radiobutton"> + <property name="label" translatable="yes">Report an error</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_backup_error_radiobutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">11</property> + <property name="bottom_attach">12</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="missing_backup_label"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes"><b>Missing Backup Devices</b></property> + <property name="use_markup">True</property> + </widget> + <packing> + <property name="right_attach">2</property> + <property name="top_attach">9</property> + <property name="bottom_attach">10</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="add_identifier_radiobutton"> + <property name="label" translatable="yes">Add unique identifier</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">skip_download_radiobutton</property> + <signal name="toggled" handler="on_add_identifier_radiobutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="skip_download_radiobutton"> + <property name="label" translatable="yes">Skip download</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">4</property> + <property name="bottom_attach">5</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">Choose whether to skip downloading the image, or to add a unique indentifier.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">3</property> + <property name="bottom_attach">4</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkCheckButton" id="indicate_download_error_checkbutton"> + <property name="label" translatable="yes">Report an error</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_indicate_download_error_checkbutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label19"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">Specify what to do when an image of the same name has already been downloaded or backed up.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label3"> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">Specify what to do when there are no backup devices.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">10</property> + <property name="bottom_attach">11</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="xalign">0</property> + <property name="ypad">12</property> + <property name="label" translatable="yes">When backing up, choose whether to overwrite an image on the backup device that has the same name, or skip backing it up.</property> + <property name="wrap">True</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">6</property> + <property name="bottom_attach">7</property> + <property name="y_options">GTK_FILL</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="backup_duplicate_overwrite_radiobutton"> + <property name="label" translatable="yes">Overwrite</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <property name="group">backup_duplicate_skip_radiobutton</property> + <signal name="toggled" handler="on_backup_duplicate_overwrite_radiobutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">7</property> + <property name="bottom_attach">8</property> + </packing> + </child> + <child> + <widget class="GtkRadioButton" id="backup_duplicate_skip_radiobutton"> + <property name="label" translatable="yes">Skip</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="active">True</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_backup_duplicate_skip_radiobutton_toggled"/> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">8</property> + <property name="bottom_attach">9</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="label37"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="position">6</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="error_label"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Error Handling</property> + </widget> + <packing> + <property name="position">6</property> + <property name="tab_fill">False</property> + <property name="type">tab</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">6</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">5</property> + <property name="position">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <widget class="GtkButton" id="help_button"> + <property name="label">gtk-help</property> + <property name="response_id">-11</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_stock">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + <property name="secondary">True</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="close_button"> + <property name="label">gtk-close</property> + <property name="response_id">-7</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + <signal name="clicked" handler="on_close_button_clicked"/> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkAboutDialog" id="about"> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="border_width">5</property> + <property name="destroy_with_parent">True</property> + <property name="icon">rapid-photo-downloader-about.png</property> + <property name="type_hint">normal</property> + <property name="program_name">Rapid Photo Downloader</property> + <property name="copyright" translatable="yes">Copyright Damon Lynch 2007-09</property> + <property name="comments" translatable="yes">Import your images efficiently and reliably</property> + <property name="website">http://www.damonlynch.net/rapid</property> + <property name="license" translatable="yes">Rapid Photo Downloader is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. + +Rapid Photo Downloader is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</property> + <property name="authors">Damon Lynch <damonlynch@gmail.com></property> + <property name="translator_credits" comments="TRANSLATORS: Replace this string with your names, one name per line.">Martin Egger <martin.egger@gmx.net> +Jose Luis Navarro <jlnavarro111@gmail.com> +Abel O'Rian <abel.orian@gmail.com> +Daniel Paessler <daniel@paessler.org> +Michal Predotka <mpredotka@googlemail.com> +Luca Reverberi <thereve@gmail.com> +Mikko Ruohola <polarfox@polarfox.net> +Sergei Sedov <sedov@webmail.perm.ru> +Marco Solari <marcosolari@gmail.com> +Julien Valroff <julien@kirya.net></property> + <property name="logo">rapid-photo-downloader-about.png</property> + <property name="wrap_license">True</property> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <placeholder/> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">end</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkWindow" id="rapidapp"> + <property name="width_request">600</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="title" translatable="yes">Rapid Photo Downloader</property> + <property name="icon">rapid-photo-downloader-about.png</property> + <signal name="destroy" handler="on_rapidapp_destroy"/> + <child> + <widget class="GtkVBox" id="vbox10"> + <property name="visible">True</property> + <child> + <widget class="GtkMenuBar" id="menubar3"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkMenuItem" id="menuitem7"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Photos</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menuitem7_menu"> + <child> + <widget class="GtkImageMenuItem" id="menu_download_pause"> + <property name="label" translatable="yes">Download / Pause</property> + <property name="visible">True</property> + <property name="use_stock">False</property> + <signal name="activate" handler="on_download_button_clicked"/> + <accelerator key="Return" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <child internal-child="image"> + <widget class="GtkImage" id="image1"> + <property name="visible">True</property> + <property name="stock">gtk-convert</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="menu_resequence"> + <property name="label">Resequence</property> + <property name="use_stock">False</property> + <accelerator key="E" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <child internal-child="image"> + <widget class="GtkImage" id="image2"> + <property name="visible">True</property> + <property name="stock">gtk-sort-descending</property> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkSeparatorMenuItem" id="separator2"/> + </child> + <child> + <widget class="GtkImageMenuItem" id="menu_preferences"> + <property name="label">gtk-preferences</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="on_menu_preferences_activate"/> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="menu_quit"> + <property name="label">gtk-quit</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="on_rapidapp_destroy"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menuitem10"> + <property name="visible">True</property> + <property name="label" translatable="yes">_View</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="menuitem10_menu"> + <child> + <widget class="GtkCheckMenuItem" id="menu_display_thumbnails"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Thumbnails</property> + <property name="use_underline">True</property> + <signal name="toggled" handler="on_menu_display_thumbnails_toggled"/> + </widget> + </child> + <child> + <widget class="GtkCheckMenuItem" id="menu_log_window"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Error Log</property> + <property name="use_underline">True</property> + <signal name="toggled" handler="on_menu_log_window_toggled"/> + </widget> + </child> + <child> + <widget class="GtkSeparatorMenuItem" id="separator5"> + <property name="visible">True</property> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menu_clear"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Clear Completed Downloads</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_menu_clear_activate"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="help_menuitem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + <child> + <widget class="GtkMenu" id="help_menu"> + <child> + <widget class="GtkMenuItem" id="menu_get_help_online"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Get Help Online...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_menu_get_help_online_activate"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menu_report_problem"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Report a Problem...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_menu_report_problem_activate"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menu_donate"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Make a Donation...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_menu_donate_activate"/> + </widget> + </child> + <child> + <widget class="GtkMenuItem" id="menu_translate"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Translate this Application...</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_menu_translate_activate"/> + </widget> + </child> + <child> + <widget class="GtkSeparatorMenuItem" id="separator1"> + <property name="visible">True</property> + </widget> + </child> + <child> + <widget class="GtkImageMenuItem" id="menu_about"> + <property name="label">gtk-about</property> + <property name="visible">True</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <signal name="activate" handler="on_menu_about_activate"/> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="main_vbox"> + <property name="visible">True</property> + <property name="spacing">12</property> + <child> + <widget class="GtkHBox" id="hbox6"> + <property name="visible">True</property> + <child> + <widget class="GtkScrolledWindow" id="media_collection_scrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <widget class="GtkViewport" id="media_collection_viewport"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkVBox" id="media_collection_vbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">0</property> + </packing> + </child> + </widget> + <packing> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="hbox8"> + <property name="visible">True</property> + <child> + <widget class="GtkScrolledWindow" id="image_scrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="vscrollbar_policy">never</property> + <child> + <widget class="GtkViewport" id="image_viewport"> + <property name="height_request">112</property> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <placeholder/> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">0</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="buttons_hbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkHBox" id="statusbar_hbox"> + <property name="visible">True</property> + <child> + <widget class="GtkHBox" id="download_progressbar_hbox"> + <property name="visible">True</property> + <child> + <placeholder/> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkStatusbar" id="rapid_statusbar"> + <property name="visible">True</property> + <property name="has_resize_grip">False</property> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child> + <widget class="GtkVSeparator" id="vseparator1"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <widget class="GtkVBox" id="vbox15"> + <property name="visible">True</property> + <child> + <widget class="GtkHSeparator" id="hseparator3"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="speed_label"> + <property name="visible">True</property> + <property name="label" translatable="yes"> </property> + <property name="width_chars">9</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">3</property> + </packing> + </child> + <child> + <widget class="GtkVSeparator" id="vseparator2"> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="position">4</property> + </packing> + </child> + <child> + <widget class="GtkEventBox" id="error_eventbox"> + <property name="visible">True</property> + <signal name="button_press_event" handler="on_error_eventbox_button_press_event"/> + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <child> + <widget class="GtkImage" id="warning_image"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="xpad">3</property> + <property name="stock">gtk-dialog-warning</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <widget class="GtkImage" id="error_image"> + <property name="visible">True</property> + <property name="xpad">3</property> + <property name="stock">gtk-dialog-error</property> + <property name="icon-size">1</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + <child> + <widget class="GtkStatusbar" id="statusbar1"> + <property name="width_request">15</property> + <property name="visible">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">6</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">2</property> + </packing> + </child> + </widget> + </child> + </widget> + <widget class="GtkDialog" id="logdialog"> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="border_width">5</property> + <property name="title" translatable="yes">Error Log</property> + <property name="default_width">600</property> + <property name="default_height">400</property> + <property name="destroy_with_parent">True</property> + <property name="icon">rapid-photo-downloader-about.png</property> + <property name="type_hint">dialog</property> + <property name="has_separator">False</property> + <signal name="close" handler="on_logdialog_close"/> + <signal name="response" handler="on_logdialog_response"/> + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox4"> + <property name="visible">True</property> + <property name="spacing">2</property> + <child> + <widget class="GtkScrolledWindow" id="log_scrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">automatic</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <widget class="GtkViewport" id="viewport1"> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <child> + <widget class="GtkTextView" id="log_textview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="editable">False</property> + <property name="cursor_visible">False</property> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="position">1</property> + </packing> + </child> + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area4"> + <property name="visible">True</property> + <property name="layout_style">end</property> + <child> + <placeholder/> + </child> + <child> + <widget class="GtkButton" id="button3"> + <property name="label">gtk-close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_stock">True</property> + </widget> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </widget> + <packing> + <property name="expand">False</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + </widget> + </child> + </widget> +</glade-interface> diff --git a/rapid/gnomeglade.py b/rapid/gnomeglade.py new file mode 100644 index 0000000..c0b0860 --- /dev/null +++ b/rapid/gnomeglade.py @@ -0,0 +1,166 @@ +### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""Utility classes for working with glade files. + +""" +# modified by Damon Lynch May 2009 to update i18n + +import gtk +import gtk.glade +import gnome +import gnome.ui +#import gettext +import config +from common import Configi18n + +class Base(object): + """Base class for all glade objects. + + This class handles loading the xml glade file and connects + all methods name 'on_*' to the signals in the glade file. + + The handle to the xml file is stored in 'self.xml'. The + toplevel widget is stored in 'self.widget'. + + In addition it calls widget.set_data("pyobject", self) - this + allows us to get the python object given only the 'raw' gtk+ + object, which is sadly sometimes necessary. + """ + + def __init__(self, file, root, override={}): + """Load the widgets from the node 'root' in file 'file'. + + Automatically connects signal handlers named 'on_*'. + """ + global _ + _ = Configi18n._ + if Configi18n.locale_path: + gtk.glade.bindtextdomain(config.APP_NAME, Configi18n.locale_path) + gtk.glade.textdomain(config.APP_NAME) + self.xml = gtk.glade.XML(file, root, typedict=override ) + handlers = {} + for h in filter(lambda x:x.startswith("on_"), dir(self.__class__)): + handlers[h] = getattr(self, h) + self.xml.signal_autoconnect( handlers ) + self.widget = getattr(self, root) + self.widget.set_data("pyobject", self) + + def __getattr__(self, key): + """Allow glade widgets to be accessed as self.widgetname. + """ + widget = self.xml.get_widget(key) + if widget: # cache lookups + setattr(self, key, widget) + return widget + raise AttributeError(key) + + def flushevents(self): + """Handle all the events currently in the main queue and return. + """ + while gtk.events_pending(): + gtk.main_iteration(); + + def _map_widgets_into_lists(self, widgetnames): + """Put sequentially numbered widgets into lists. + + e.g. If an object had widgets self.button0, self.button1, ..., + then after a call to object._map_widgets_into_lists(["button"]) + object has an attribute self.button == [self.button0, self.button1, ...]." + """ + for item in widgetnames: + setattr(self,item, []) + lst = getattr(self,item) + i = 0 + while 1: + key = "%s%i"%(item,i) + try: + val = getattr(self, key) + except AttributeError: + break + lst.append(val) + i += 1 + + +class Component(Base): + """A convenience base class for widgets which use glade. + """ + + def __init__(self, file, root, override={}): + Base.__init__(self, file, root, override) + + +class GtkApp(Base): + """A convenience base class for gtk+ apps created in glade. + """ + + def __init__(self, file, root=None): + Base.__init__(self, file, root) + + def main(self): + """Enter the gtk main loop. + """ + gtk.main() + + def quit(self, *args): + """Signal the gtk main loop to quit. + """ + gtk.main_quit() + + +class GnomeApp(GtkApp): + """A convenience base class for apps created in glade. + """ + + def __init__(self, name, version, file, root): + """Initialise program 'name' and version from 'file' containing root node 'root'. + """ + self.program = gnome.program_init(name, version) + GtkApp.__init__(self,file,root) + if 0: + self.client = gnome.ui.Client() + self.client.disconnect() + def connected(*args): + print "CONNECTED", args + def cb(name): + def cb2(*args): + print name, args, "\n" + return cb2 + self.client.connect("connect", cb("CON")) + self.client.connect("die", cb("DIE")) + self.client.connect("disconnect", cb("DIS")) + self.client.connect("save-yourself", cb("SAVE")) + self.client.connect("shutdown-cancelled", cb("CAN")) + self.client.connect_to_session_manager() + + +def load_pixbuf(fname, size=0): + """Load an image from a file as a pixbuf, with optional resizing. + """ + image = gtk.Image() + image.set_from_file(fname) + image = image.get_pixbuf() + if size: + aspect = float(image.get_height()) / image.get_width() + image = image.scale_simple(size, int(aspect*size), 2) + return image + +def url_show(url): + return gnome.url_show(url) + +def FileEntry(*args): + return gnome.ui.FileEntry(*args) + diff --git a/rapid/higdefaults.py b/rapid/higdefaults.py new file mode 100644 index 0000000..9dfd7e5 --- /dev/null +++ b/rapid/higdefaults.py @@ -0,0 +1,8 @@ +# -*- coding: latin1 -*- +VERTICAL_CONTROL_LABEL_SPACE = CONTROL_LABEL_SPACE = 12 +CONTROL_IN_TABLE_SPACE = 6 +WINDOW_BORDER_SPACE = 12 +NESTED_CONTROLS_SPACE = 24 +VERTICAL_CONTROL_SPACE = 18 +VERTICAL_GROUP_SPACE = 24 +HORIZONTAL_GROUP_SPACE = 24 diff --git a/rapid/idletube.py b/rapid/idletube.py new file mode 100644 index 0000000..86ff1a4 --- /dev/null +++ b/rapid/idletube.py @@ -0,0 +1,205 @@ + +# Copyright (c) 2005 Antoon Pardon +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +from threading import Lock +from thread import get_ident + +from types import BooleanType as UnConnected + +UnRegistered, Registered = False, True + +class EOInformation(Exception): + pass + +class TubeAccess(Exception): + pass + +class Fifo: + + def __init__(self): + self.fifo = [] + + def put(self, item): + self.fifo.append(item) + + def get(self): + return self.fifo.pop(0) + + def size(self): + return len(self.fifo) + +class Tube: + + def __init__(self, maxsize, lck = Lock, container = None): + if container is None: + container = Fifo() + self.readers = set() + self.writers = set() + self.container = container + self.maxsize = maxsize + self.cb_arglst = [] + self.cb_src = UnRegistered + self.in_use = Lock() + self.nowriter = lck() + self.full = lck() + self.empty = lck() + self.empty.acquire() + self.nowriter.acquire() + + def open(self, access = 'r', *to): + thrd = get_ident() + access = access.lower() + self.in_use.acquire() + if 'w' in access: + if len(self.writers) == 0: + for _ in self.readers: + self.nowriter.release() + self.writers.add(thrd) + if 'r' in access: + self.readers.add(thrd) + if len(self.writers) == 0: + self.in_use.release() + self.nowriter.acquire(*to) + else: + self.in_use.release() + else: + self.in_use.release() + + def close(self, access = 'rw'): + thrd = get_ident() + access = access.lower() + self.in_use.acquire() + if 'r' in access: + self.readers.discard(thrd) + if 'w' in access: + self.writers.discard(thrd) +## print "have", self.writers, "writers" + if len(self.writers) == 0: + if self.container.size() == 0: +## print "emptying container, as size is", self.container.size() + self.empty.release() + if self.cb_src is Registered and len(self.readers) > 0: +## print "adding callback" + self.cb_src = gob.idle_add(self._idle_callback) +## else: +## print "container size not empty, is", self.container.size() + for _ in self.readers: +## print "putting EOInformation" + self.container.put(EOInformation) + self.in_use.release() + + def size(self): + self.in_use.acquire() + size = self.container.size() + self.in_use.release() + return size + + def get(self, *to): + thrd = get_ident() + if thrd not in self.readers: + raise TubeAccess, "Thread has no read access for tube" + self.empty.acquire(*to) + self.in_use.acquire() + size = self.container.size() + if size == self.maxsize: + self.full.release() + item = self.container.get() + if size != 1: + self.empty.release() + elif type(self.cb_src) is not UnConnected: + gob.source_remove(self.cb_src) + self.cb_src = Registered + self.in_use.release() + if item is EOInformation: + raise EOInformation + else: + return item + + def put(self, item, *to): + thrd = get_ident() + if thrd not in self.writers: + raise TubeAccess, "Thread has no write access for tube" + if thrd in self.readers: + self._put_rw(item) + else: + self._put_wo(item, *to) + + def _put_wo(self, item, *to): + self.full.acquire(*to) + self.in_use.acquire() + size = self.container.size() + if size == 0: + self.empty.release() + if self.cb_src is Registered: + #gdk.threads_enter() + self.cb_src = gob.idle_add(self._idle_callback) + #gdk.threads_leave() + self.container.put(item) + if size + 1 < self.maxsize: + self.full.release() + self.in_use.release() + + def _put_rw(self, item): + self.in_use.acquire() + size = self.container.size() + if size == 0: + self.empty.release() + if self.cb_src is Registered: + self.cb_src = gob.idle_add(self._idle_callback) + self.container.put(item) + self.in_use.release() + + def _idle_callback(self): + self.in_use.acquire() + lst = self.cb_arglst.pop(0) + self.in_use.release() + func = lst[0] + lst[0] = self + ret_val = func(*lst) + self.in_use.acquire() + if ret_val: + lst[0] = func + self.cb_arglst.append(lst) + elif self.cb_arglst == []: + self.cb_src = UnRegistered + self.in_use.release() + return self.cb_src is not UnRegistered + + +def tube_add_watch(tube, callback, *args): + + global gob #, gdk + import gobject as gob + #import gtk.gdk as gdk + + tube.in_use.acquire() + tube.cb_arglst.append([callback] + list(args)) + if tube.cb_src is UnRegistered: + if tube.container.size() == 0: + tube.cb_src = Registered + else: + tube.cb_src = gob.idle_add(tube._idle_callback) + tube.in_use.release() + +def tube_remove_watch(tube): +## tube.in_use.acquire() +## gob.source_remove(tube.cb_src) +## tube._idle_callback.handler_block(tube.cb_src) + pass diff --git a/rapid/media.py b/rapid/media.py new file mode 100755 index 0000000..f4342c6 --- /dev/null +++ b/rapid/media.py @@ -0,0 +1,180 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os + +import config +import common + +import operator + +def getDefaultPhotoLocation(): + for default in config.DEFAULT_PHOTO_LOCATIONS: + path = common.getFullPath(default) + if os.path.isdir(path): + return path + return common.getFullPath('') + +def isImageMedia(path): + """ Returns true if directory specifies some media with photos on it """ + + if os.path.isdir(os.path.join(path, "DCIM")): + # is very likely a memory card, or something like that! + return True + else: + return False + + +def isBackupMedia(path, identifier, writeable=True): + """ Test to see if path is used as a backup medium for storing images + + If writeable is True, the directory must be writeable by the user """ + suitable = False + if os.path.isdir(os.path.join(path, identifier)): + if writeable: + suitable = os.access(os.path.join(path, identifier), os.W_OK) + else: + suitable = True + return suitable + +def isImage(fileName): + ext = os.path.splitext(fileName)[1].lower()[1:] + return (ext in config.RAW_FILE_EXTENSIONS) or (ext in config.NON_RAW_IMAGE_FILE_EXTENSIONS) + +class Media: + """ Generic class for media holding images """ + def __init__(self, path, volume = None): + """ + volume is a gnomevfs volume + """ + + self.path = path + self.volume = volume + + + def prettyName(self, limit=config.MAX_LENGTH_DEVICE_NAME): + """ + Returns a name for the media, useful for display. + + If the media is from a gnomevfs volume, returns the gnome name. + + Else. returns the last part of the mount point after stripping out + underscores. + """ + + if self.volume: + return self.volume.get_name(limit) + else: + name = os.path.split(self.path)[1] + name = name.replace('_', ' ') + v = name + if limit: + if len(v) > limit: + v = v[:limit] + '...' + return v + + def getPath(self): + return self.path + + +class CardMedia(Media): + """Compact Flash cards, etc.""" + def __init__(self, path, volume = None, doNotScan=True): + """ + volume is a gnomevfs volume + """ + Media.__init__(self, path, volume) + if not doNotScan: + self.scanMedia() + + def scanMedia(self): + """ creates a list of images on a path, recursively scanning + + images are sorted by modification time""" + + self.images = [] + self.imageSizeSum = 0 + for root, dirs, files in os.walk(self.path): + for name in files: + if isImage(name): + image = os.path.join(root, name) + size = os.path.getsize(image) + modificationTime = os.path.getmtime(image) + self.images.append((name, root, size, modificationTime),) + self.imageSizeSum += size + self.images.sort(key=operator.itemgetter(3)) + self.noImages = len(self.images) + + def setMedia(self, images, imageSizeSum, noImages): + self.images = images + self.imageSizeSum = imageSizeSum + self.noImages = noImages + + def numberOfImages(self): + return self.noImages + + def sizeOfImages(self, humanReadable = True): + if humanReadable: + return common.formatSizeForUser(self.imageSizeSum) + else: + return self.imageSizeSum + + def firstImage(self): + if self.images: + return self.images[0] + else: + return None + + +def scanForImageMedia(path): + """ returns a list of paths that contain images on media produced by a digital camera """ + + media = [] + for i in os.listdir(path): + p = os.path.join(path, i) + if os.path.isdir(p): + if isImageMedia(p): + media.append(p) + return media + +def scanForBackupMedia(path, identifier): + """ returns a list of paths that contains backed up images """ + + media = [] + for i in os.listdir(path): + p = os.path.join(path, i) + if os.path.isdir(p): + if isBackupMedia(p, identifier): + media.append(os.path.join(p, identifier)) + return media + + +if __name__ == '__main__': + print "Card media:" + for m in scanForImageMedia('/media'): + media = CardMedia(m) + print media.prettyName() + print media.numberOfImages() + print media.sizeOfImages() + + print "\nBackup media:" + for m in scanForBackupMedia('/media', 'photos'): + print m + + print "\nDefault download folder: ", getDefaultPhotoLocation() diff --git a/rapid/metadata.py b/rapid/metadata.py new file mode 100755 index 0000000..8fc6820 --- /dev/null +++ b/rapid/metadata.py @@ -0,0 +1,387 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import re +import datetime +import sys +import config + +try: + import pyexiv2 +except ImportError: + sys.stderr.write("You need to install pyexiv2, the python binding for exiv2, to run this program.\n" ) + sys.exit(1) + +#only pyexiv2 0.1.2 and 0.1.3 use the "Rational" class +#is there a superior way to find which version of pyexiv2 is being used? +if 'Rational' in dir(pyexiv2): + usesRational = True +else: + usesRational = False + + +class MetaData(pyexiv2.Image): + """ + Class providing human readable access to image metadata + """ + + def aperture(self, missing=''): + """ + Returns in string format the floating point value of the image's aperture. + + Returns missing if the metadata value is not present. + """ + + try: + if usesRational: + a = self["Exif.Photo.FNumber"] + a0, a1 = str(a).split('/') + else: + a0, a1 = self["Exif.Photo.FNumber"] + a = float(a0) / float(a1) + return "%.1f" % a + except: + return missing + + def iso(self, missing=''): + """ + Returns in string format the integer value of the image's ISO. + + Returns missing if the metadata value is not present. + """ + try: + return "%s" % (self["Exif.Photo.ISOSpeedRatings"]) + except: + return missing + + def exposureTime(self, alternativeFormat=False, missing=''): + """ + Returns in string format the exposure time of the image. + + Returns missing if the metadata value is not present. + + alternativeFormat is useful if the value is going to be used in a + purpose where / is an invalid character, e.g. file system names. + + alternativeFormat is False: + For exposures less than one second, the result is formatted as a + fraction e.g. 1/125 + For exposures greater than or equal to one second, the value is + formatted as an integer e.g. 30 + + alternativeFormat is True: + For exposures less than one second, the result is formatted as an + integer e.g. 125 + For exposures less than one second but more than or equal to + one tenth of a second, the result is formatted as an integer + e.g. 3 representing 3/10 of a second + For exposures greater than or equal to one second, the value is + formatted as an integer with a trailing s e.g. 30s + """ + + try: + if usesRational: + e = str(self["Exif.Photo.ExposureTime"]) + e0, e1 = e.split('/') + e0 = int(e0) + e1 = int(e1) + else: + e0, e1 = self["Exif.Photo.ExposureTime"] + + if e1 > e0: + if alternativeFormat: + if e0 == 1: + return str(e1) + else: + return str(e0) + else: + return e + elif e0 > e1: + e = float(e0) / e1 + if alternativeFormat: + return "%.0fs" % e + else: + return "%.0f" % e + else: + return "1s" + except: + return missing + + def focalLength(self, missing=''): + """ + Returns in string format the focal length of the lens used to record the image. + + Returns missing if the metadata value is not present. + """ + try: + if usesRational: + f = str(self["Exif.Photo.FocalLength"]) + f0, f1 = f.split('/') + else: + f0, f1 = self["Exif.Photo.FocalLength"] + + f0 = float(f0) + if not f1: + f1 = 1.0 + else: + f1 = float(f1) + + return "%.0f" % (f0 / f1) + except: + return missing + + + def cameraMake(self, missing=''): + """ + Returns in string format the camera make (manufacturer) used to record the image. + + Returns missing if the metadata value is not present. + """ + try: + return self["Exif.Image.Make"].strip() + except: + return missing + + def cameraModel(self, missing=''): + """ + Returns in string format the camera model used to record the image. + + Returns missing if the metadata value is not present. + """ + try: + return self["Exif.Image.Model"].strip() + except: + return missing + + def cameraSerial(self, missing=''): + try: + keys = self.exifKeys() + if 'Exif.Canon.SerialNumber' in keys: + v = self['Exif.Canon.SerialNumber'] + elif 'Exif.Nikon3.SerialNumber' in keys: + v = self['Exif.Nikon3.SerialNumber'] + elif 'Exif.OlympusEq.SerialNumber' in keys: + v = self['Exif.OlympusEq.SerialNumber'] + elif 'Exif.Olympus.SerialNumber' in keys: + v = self['Exif.Olympus.SerialNumber'] + elif 'Exif.Olympus.SerialNumber2' in keys: + v = self['Exif.Olympus.SerialNumber2'] + elif 'Exif.Panasonic.SerialNumber' in keys: + v = self['Exif.Panasonic.SerialNumber'] + elif 'Exif.Fujifilm.SerialNumber' in keys: + v = self['Exif.Fujifilm.SerialNumber'] + elif 'Exif.Image.CameraSerialNumber' in keys: + v = self['Exif.Image.CameraSerialNumber'] + else: + return missing + return str(v) + except: + return missing + + def shutterCount(self, missing=''): + try: + keys = self.exifKeys() + if 'Exif.Nikon3.ShutterCount' in keys: + v = self['Exif.Nikon3.ShutterCount'] + elif 'Exif.Canon.ImageNumber' in keys: + v = self['Exif.Canon.ImageNumber'] + else: + return missing + return str(v) + except: + return missing + + def ownerName(self, missing=''): + """ returns camera name recorded by select Canon cameras""" + try: + return self['Exif.Canon.OwnerName'].strip() + except: + return missing + + def shortCameraModel(self, includeCharacters = '', missing=''): + """ + Returns in shorterned string format the camera model used to record the image. + + Returns missing if the metadata value is not present. + + The short format is determined by the first occurence of a digit in the + camera model, including all alphaNumeric characters before and after + that digit up till a non-alphanumeric character. + + Canon "Mark" designations are shortened prior to conversion. + + Examples: + Canon EOS 300D DIGITAL -> 300D + Canon EOS 5D -> 5D + Canon EOS 5D Mark II -> 5DMkII + NIKON D2X -> D2X + NIKON D70 -> D70 + X100,D540Z,C310Z -> X100 + + The optional includeCharacters allows additional characters to appear + before and after the digits. + Note: special includeCharacters MUST be escaped as per syntax of a + regular expressions (see documentation for module re) + + Examples: + + includeCharacters = '': + DSC-P92 -> P92 + includeCharacters = '\-': + DSC-P92 -> DSC-P92 + + If a digit is not found in the camera model, the full length camera + model is returned. + + Note: assume exif values are in ENGLISH, regardless of current platform + """ + m = self.cameraModel() + m = m.replace(' Mark ', 'Mk') + if m: + s = r"(?:[^a-zA-Z0-9%s]?)(?P<model>[a-zA-Z0-9%s]*\d+[a-zA-Z0-9%s]*)"\ + % (includeCharacters, includeCharacters, includeCharacters) + r = re.search(s, m) + if r: + return r.group("model") + else: + return m.strip() + else: + return missing + + def dateTime(self, missing=''): + """ + Returns in python datetime format the date and time the image was + recorded. + + Trys to get value from exif key "Exif.Photo.DateTimeOriginal". + If that does not exist, trys key "Exif.Image.DateTime" + + Returns missing either metadata value is not present. + """ + keys = self.exifKeys() + try: + if "Exif.Photo.DateTimeOriginal" in keys: + return self["Exif.Photo.DateTimeOriginal"] + else: + return self["Exif.Image.DateTime"] + except: + return missing + + def subSeconds(self, missing='00'): + """ returns the subsecond the image was taken, as recorded by the camera""" + try: + return str(self["Exif.Photo.SubSecTimeOriginal"]) + except: + return missing + + def orientation(self, missing=''): + """ + Returns the orientation of the image, as recorded by the camera + """ + try: + return self['Exif.Image.Orientation'] + except: + return missing + +class DummyMetaData(MetaData): + """ + Class which gives metadata values for an imaginary image. + + Useful for displaying in preference examples etc. when no image is ready to + be downloaded. + + See MetaData class for documentation of class methods. + """ + + def __init__(self): + pass + + def readMetadata(self): + pass + + def aperture(self, missing=''): + return "2.0" + + def iso(self, missing=''): + return "100" + + def exposureTime(self, alternativeFormat=False, missing=''): + if alternativeFormat: + return "4000" + else: + return "1/4000" + + def focalLength(self, missing=''): + return "135" + + def cameraMake(self, missing=''): + return "Canon" + + def cameraModel(self, missing=''): + return "Canon EOS 5D" + + def shortCameraModel(self, includeCharacters = '', missing=''): + return "5D" + + def cameraSerial(self, missing=''): + return '730402168' + + def shutterCount(self, missing=''): + return '387' + + def ownerName(self, missing=''): + return 'Photographer Name' + + def dateTime(self, missing=''): + return datetime.datetime.now() + + def subSeconds(self, missing='00'): + return '57' + + def orientation(self, missing=''): + return 1 + +if __name__ == '__main__': + import sys + + if (len(sys.argv) != 2): + print 'Usage: ' + sys.argv[0] + ' path/to/photo/containing/metadata' + m = DummyMetaData() + + else: + m = MetaData(sys.argv[1]) + m.readMetadata() + +# for i in m.exifKeys(): +# print i + print "f"+ m.aperture('missing ') + print "ISO " + m.iso('missing ') + print m.exposureTime(missing='missing ') + " sec" + print m.exposureTime(alternativeFormat=True, missing='missing ') + print m.focalLength('missing ') + "mm" + print m.cameraMake() + print m.cameraModel() + print m.shortCameraModel() + print m.shortCameraModel(includeCharacters = "\-") + print m.dateTime() + print m.orientation() + print 'Serial number:', m.cameraSerial() + print 'Shutter count:', m.shutterCount() + print 'Subseconds:', m.subSeconds() + diff --git a/rapid/misc.py b/rapid/misc.py new file mode 100644 index 0000000..1e023ad --- /dev/null +++ b/rapid/misc.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# modified by Damon Lynch 2009 to remove default bold formatting and alignment +"""Module of commonly used helper classes and functions + +""" + +import gtk + +def run_dialog( text, secondarytext=None, parent=None, messagetype=gtk.MESSAGE_WARNING, buttonstype=gtk.BUTTONS_OK, extrabuttons=[]): + """Run a dialog with text 'text'. + Extra buttons are passed as tuples of (button label, response id). + """ + d = gtk.MessageDialog(None, + gtk.DIALOG_DESTROY_WITH_PARENT, + messagetype, + buttonstype, + text + ) + if parent: + d.set_transient_for(parent.widget.get_toplevel()) + for b,rid in extrabuttons: + d.add_button(b,rid) + d.vbox.set_spacing(12) + d.format_secondary_text(secondarytext) + ret = d.run() + d.destroy() + return ret diff --git a/rapid/paths.py b/rapid/paths.py new file mode 100644 index 0000000..0653324 --- /dev/null +++ b/rapid/paths.py @@ -0,0 +1,40 @@ +### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import os + +_locale_dir = ( #LOCALEDIR# +) +_help_dir = ( #HELPDIR# +) +_share_dir = ( #SHAREDIR# +) + +appdir = os.path.dirname(__file__) + +if not _locale_dir: _locale_dir = os.path.join(appdir,"po") +if not _help_dir: _help_dir = os.path.join(appdir,"help") +if not _share_dir: _share_dir = appdir + +def locale_dir(*args): # i18n files + return os.path.join(_locale_dir, *args) + +def help_dir(*args): # help + return os.path.join(_help_dir, *args) + +def share_dir(*args): # glade + pixmaps + return os.path.join(_share_dir, *args) + diff --git a/rapid/prefs.py b/rapid/prefs.py new file mode 100644 index 0000000..6912138 --- /dev/null +++ b/rapid/prefs.py @@ -0,0 +1,182 @@ +### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +### Modified August 2007 by Damon Lynch to allow use of list value preferences + +"""Module to help implement 'instant-apply' preferences. + +Usage: + +import prefs +defaults = { + "colour" : prefs.Value(prefs.STRING, "red") + "size" : prefs.Value(prefs.INT, 10) +} + +p = prefs.Preferences("/apps/myapp", defaults) +# use variables as if they were normal attributes. +draw(p.colour, p.size) +# settings are persistent. (saved in gconf) +p.color = "blue" + +""" + +class Value(object): + """Represents a settable preference. + """ + + __slots__ = ["type", "default", "current"] + + def __init__(self, t, d): + """Create a value. + + t : a string : one of ("bool", "int", "string", "list") + d : the default value, also the initial value + """ + self.type = t + self.default = d + self.current = d + + def setfunc(self, gconf, rootkey, attr): + setfunc = getattr(gconf, "set_%s" % self.type) + setfunc("%s/%s" % (rootkey, attr), self.current) + + def getfunc(self, gconf, rootkey, attr): + getfunc = getattr(gconf, "get_%s" % self.type) + return getfunc("%s/%s" % (rootkey, attr)) + + +class ListValue(Value): + """ + Represents a list type settable preference. + """ + + __slots__ = Value.__slots__ + ["list_type"] + def __init__(self, list_type, d): + """ + Create a list value. + + d : the default value, also the initial value + list_type: the type of elements the list contains + """ + Value.__init__(self, LIST, d) + self.list_type = list_type + + def setfunc(self, gconf, rootkey, attr): + setfunc = getattr(gconf, "set_list") + setfunc("%s/%s" % (rootkey, attr), self.list_type, self.current) + + def getfunc(self, gconf, rootkey, attr): + getfunc = getattr(gconf, "get_list") + return getfunc("%s/%s" % (rootkey, attr), self.list_type) + + +# maybe fall back to ConfigParser if gconf is unavailable. +import gconf + +# types of values allowed +BOOL = "bool" +INT = "int" +STRING = "string" +FLOAT = "float" +LIST = "list" +# PAIR = "pair" +STRING_LIST = gconf.VALUE_STRING +INT_LIST = gconf.VALUE_INT +BOOL_LIST = gconf.VALUE_BOOL +FLOAT_LIST = gconf.VALUE_FLOAT +## + +class Preferences(object): + """Persistent preferences object. + + Example: + import prefs + defaults = {"spacing": prefs.Value(prefs.INT, 4), + "font": prefs.Value(prefs.STRING, "monospace") } + p = prefs.Prefs("myapp", defaults) + print p.font + p.font = "sans" # written to gconf too + p2 = prefs.Prefs("myapp", defaults) + print p.font # prints "sans" + """ + + def __init__(self, rootkey, initial): + """Create a preferences object. + + Settings are initialised with 'initial' and then overriden + from values in the gconf database if available. + + rootkey : the root gconf key where the values will be stored + initial : a dictionary of string to Value objects. + """ + self.__dict__["_gconf"] = gconf.client_get_default() + self.__dict__["_listeners"] = [] + self.__dict__["_rootkey"] = rootkey + self.__dict__["_prefs"] = initial + self._gconf.add_dir(rootkey, gconf.CLIENT_PRELOAD_NONE) + self._gconf.notify_add(rootkey, self._on_preference_changed) + for key, value in self._prefs.items(): + gval = self._gconf.get_without_default("%s/%s" % (rootkey, key) ) + if gval != None: + value.current = value.getfunc(self._gconf, rootkey, key) + + def __getattr__(self, attr): + return self._prefs[attr].current + + def get_default(self, attr): + return self._prefs[attr].default + + def __setattr__(self, attr, val): + value = self._prefs[attr] + + if value.current != val: + value.current = val + value.setfunc(self._gconf, self._rootkey, attr) + + try: + for l in self._listeners: + l(attr,val) + except StopIteration: + pass + + def _on_preference_changed(self, client, timestamp, entry, extra): + attr = entry.key[ entry.key.rindex("/")+1 : ] + try: + valuestruct = self._prefs[attr] + except KeyError: # unknown key, we don't care about it + pass + else: + if entry.value != None: # value has changed + newval = valuestruct.getfunc(self._gconf, self._rootkey, attr) + setattr( self, attr, newval) + else: # value has been deleted + setattr( self, attr, valuestruct.default ) + + def notify_add(self, callback): + """Register a callback to be called when a preference changes. + + callback : a callable object which take two parameters, 'attr' the + name of the attribute changed and 'val' the new value. + """ + self._listeners.append(callback) + + def dump(self): + """Print all preferences. + """ + for k,v in self._prefs.items(): + print k, v.type, v.current + diff --git a/rapid/rapid.py b/rapid/rapid.py new file mode 100755 index 0000000..0dcbb21 --- /dev/null +++ b/rapid/rapid.py @@ -0,0 +1,3050 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +#needed for python 2.5, unneeded for python 2.6 +from __future__ import with_statement + +import sys +import os +import shutil +import time +import datetime +import atexit +import tempfile +import webbrowser +import operator + +import dbus +import dbus.bus +import dbus.service +from dbus.mainloop.glib import DBusGMainLoop +DBusGMainLoop(set_as_default=True) + +from threading import Thread, Lock +from thread import error as thread_error +from thread import get_ident + +import gtk.gdk as gdk +import pango + +try: + import gio + using_gio = True +except ImportError: + import gnomevfs + using_gio = False + + +import prefs +import paths +import gnomeglade + +from optparse import OptionParser + +import pynotify + +import ValidatedEntry + +import idletube as tube + +import config +import common +import misc +import higdefaults as hd + +from media import getDefaultPhotoLocation +from media import CardMedia + +import media + +import metadata + +import renamesubfolderprefs as rn + +import tableplusminus as tpm + +__version__ = config.version + +try: + import pygtk + pygtk.require("2.0") +except: + pass +try: + import gtk + import gtk.glade +except: + sys.exit(1) + +from common import Configi18n +global _ +_ = Configi18n._ + +#Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +PROGRAM_NAME = _('Rapid Photo Downloader') + +def today(): + return datetime.date.today().strftime('%Y-%m-%d') + + + +def cmd_line(msg): + if verbose: + print msg + +exiting = False + +def updateDisplay(display_queue): + + try: + if display_queue.size() != 0: + call, args = display_queue.get() + if not exiting: + call(*args) +# else do not update display + else: + sys.stderr.write("Empty display queue!\n") + return True + + except tube.EOInformation: + for w in workers.getStartedWorkers(): + w.join() + gtk.main_quit() + + return False + + +class Queue(tube.Tube): + def __init__(self, maxSize = config.MAX_NO_READERS): + tube.Tube.__init__(self, maxSize) + + def setMaxSize(self, maxSize): + self.maxsize = maxSize + + +# Module wide values - +# set up thesse variable in global name space, and initialize with proper +# values later +# this is ugly but I don't know a better way :( + +display_queue = Queue() +media_collection_treeview = image_hbox = log_dialog = None + + +class ThreadManager: + _workers = [] + + + def append(self, w): + self._workers.append(w) + + def __getitem__(self, i): + return self._workers[i] + + def __len__(self): + return len(self._workers) + + def disableWorker(self, thread_id): + """ + set so a worker will not run, or if it is running, make it quit and therefore complete + """ + + self._workers[thread_id].manuallyDisabled = True + if self._workers[thread_id].hasStarted: + self._workers[thread_id].quit() + + else: + self._workers[thread_id].doNotStart = True + + def _isReadyToStart(self, w): + """ + Returns True if the worker is ready to start + and has not been disabled + """ + return not w.hasStarted and not w.doNotStart and not w.manuallyDisabled + + def _isReadyToDownload(self, w): + return w.scanComplete and not w.downloadStarted and not w.doNotStart and w.isAlive() and not w.manuallyDisabled + + def _isDownloading(self, w): + return w.downloadStarted and w.isAlive() and not w.downloadComplete + + def _isFinished(self, w): + """ + Returns True if the worker has finished running + + It does not signify it finished a download + """ + + return (w.hasStarted and not w.isAlive()) or w.manuallyDisabled + + def completedDownload(self, w): + return w.completedDownload + + def firstWorkerReadyToStart(self): + for w in self._workers: + if self._isReadyToStart(w): + return w + return None + + def firstWorkerReadyToDownload(self): + for w in self._workers: + if self._isReadyToDownload(w): + return w + return None + + def startWorkers(self): + for w in self.getReadyToStartWorkers(): + w.start() + + def startDownloadingWorkers(self): + for w in self.getReadyToDownloadWorkers(): + w.startStop() + + def quitAllWorkers(self): + global exiting + exiting = True + for w in self._workers: + w.quit() + + def getWorkers(self): + for w in self._workers: + yield w + + def getNonFinishedWorkers(self): + for w in self._workers: + if not self._isFinished(w): + yield w + + def getStartedWorkers(self): + for w in self._workers: + if w.hasStarted: + yield w + + def getReadyToStartWorkers(self): + for w in self._workers: + if self._isReadyToStart(w): + yield w + + def getReadyToDownloadWorkers(self): + for w in self._workers: + if self._isReadyToDownload(w): + yield w + + def getNotDownloadingWorkers(self): + for w in self._workers: + if w.hasStarted and not w.downloadStarted: + yield w + + def noReadyToStartWorkers(self): + n = 0 + for w in self._workers: + if self._isReadyToStart(w): + n += 1 + return n + + def noReadyToDownloadWorkers(self): + n = 0 + for w in self._workers: + if self._isReadyToDownload(w): + n += 1 + return n + + def getRunningWorkers(self): + for w in self._workers: + if w.hasStarted and w.isAlive(): + yield w + + def getDownloadingWorkers(self): + for w in self._workers: + if self._isDownloading(w): + yield w + + + def getPausedWorkers(self): + for w in self._workers: + if w.hasStarted and not w.running: + yield w + + def getPausedDownloadingWorkers(self): + for w in self._workers: + if w.downloadStarted and not w.running: + yield w + + def getFinishedWorkers(self): + for w in self._workers: + if self._isFinished(w): + yield w + + def noDownloadingWorkers(self): + i = 0 + for w in self._workers: + if self._isDownloading(w): + i += 1 + return i + + def noRunningWorkers(self): + i = 0 + for w in self._workers: + if w.hasStarted and w.isAlive(): + i += 1 + return i + + def getNextThread_id(self): + return len(self._workers) + + def printWorkerStatus(self, worker=None): + if worker: + l = [worker] + else: + l = range(len(self._workers)) + for i in l: + print "\nThread %i\n=======\n" % i + w = self._workers[i] + print "Volume / source:", w.cardMedia.prettyName(limit=0) + print "Do not start:", w.doNotStart + print "Started:", w.hasStarted + print "Running:", w.running + print "Scan completed:", w.scanComplete + print "Download started:", w.downloadStarted + print "Download completed:", w.downloadComplete + print "Finished:", self._isFinished(w) + print "Alive:", w.isAlive() + print "Manually disabled:", w.manuallyDisabled, "\n" + + + +workers = ThreadManager() + +class RapidPreferences(prefs.Preferences): + defaults = { + "program_version": prefs.Value(prefs.STRING, ""), + "download_folder": prefs.Value(prefs.STRING, + getDefaultPhotoLocation()), + "subfolder": prefs.ListValue(prefs.STRING_LIST, rn.DEFAULT_SUBFOLDER_PREFS), + "image_rename": prefs.ListValue(prefs.STRING_LIST, [rn.FILENAME, + rn.NAME_EXTENSION, + rn.ORIGINAL_CASE]), + "device_autodetection": prefs.Value(prefs.BOOL, True), + "device_location": prefs.Value(prefs.STRING, os.path.expanduser('~')), + "device_autodetection_psd": prefs.Value(prefs.BOOL, False), + "backup_images": prefs.Value(prefs.BOOL, False), + "backup_device_autodetection": prefs.Value(prefs.BOOL, True), + "backup_identifier": prefs.Value(prefs.STRING, + config.DEFAULT_BACKUP_LOCATION), + "backup_location": prefs.Value(prefs.STRING, os.path.expanduser('~')), + "strip_characters": prefs.Value(prefs.BOOL, True), + "auto_download_at_startup": prefs.Value(prefs.BOOL, False), + "auto_download_upon_device_insertion": prefs.Value(prefs.BOOL, False), + "auto_unmount": prefs.Value(prefs.BOOL, False), + "auto_exit": prefs.Value(prefs.BOOL, False), + "indicate_download_error": prefs.Value(prefs.BOOL, True), + "download_conflict_resolution": prefs.Value(prefs.STRING, + config.SKIP_DOWNLOAD), + "backup_duplicate_overwrite": prefs.Value(prefs.BOOL, False), + "backup_missing": prefs.Value(prefs.STRING, config.IGNORE), + "display_thumbnails": prefs.Value(prefs.BOOL, True), + "show_log_dialog": prefs.Value(prefs.BOOL, False), + "day_start": prefs.Value(prefs.STRING, "03:00"), + "downloads_today": prefs.ListValue(prefs.STRING_LIST, [today(), '0']), + "stored_sequence_no": prefs.Value(prefs.INT, 0), + } + + def __init__(self): + prefs.Preferences.__init__(self, config.GCONF_KEY, self.defaults) + + def getAndMaybeResetDownloadsToday(self): + v = self.getDownloadsToday() + if v <= 0: + self.resetDownloadsToday() + return v + + def getDownloadsToday(self): + """Returns the preference value for the number of downloads performed today + + If value is less than zero, that means the date has changed""" + + hour, minute = self.getDayStart() + adjustedToday = datetime.datetime.strptime("%s %s:%s" % (self.downloads_today[0], hour, minute), "%Y-%m-%d %H:%M") + + now = datetime.datetime.today() + + if now < adjustedToday : + try: + return int(self.downloads_today[1]) + except ValueError: + sys.stderr.write(_("Invalid Downloads Today value.\n")) + sys.stderr.write(_("Resetting value to zero.\n")) + self.setDownloadsToday(self.downloads_today[0] , 0) + return 0 + else: + return -1 + + def setDownloadsToday(self, date, value=0): + self.downloads_today = [date, str(value)] + + def incrementDownloadsToday(self): + """ returns true if day changed """ + v = self.getDownloadsToday() + if v >= 0: + self.setDownloadsToday(self.downloads_today[0] , v + 1) + return False + else: + self.resetDownloadsToday(1) + return True + + def resetDownloadsToday(self, value=0): + now = datetime.datetime.today() + hour, minute = self.getDayStart() + t = datetime.time(hour, minute) + if now.time() < t: + date = today() + else: + d = datetime.datetime.today() + datetime.timedelta(days=1) + date = d.strftime(('%Y-%m-%d')) + + self.setDownloadsToday(date, value) + + def setDayStart(self, hour, minute): + self.day_start = "%s:%s" % (hour, minute) + + def getDayStart(self): + try: + t1, t2 = self.day_start.split(":") + return (int(t1), int(t2)) + except ValueError: + sys.stderr.write(_("'Start of day' preference value is corrupted.\n")) + sys.stderr.write(_("Resetting to midnight.\n")) + self.day_start = "0:0" + return 0, 0 + + +class ImageRenameTable(tpm.TablePlusMinus): + + def __init__(self, parentApp, adjustScrollWindow): + + tpm.TablePlusMinus.__init__(self, 1, 3) + self.parentApp = parentApp + self.adjustScrollWindow = adjustScrollWindow + if adjustScrollWindow: + self.connect("size-request", self.size_adjustment) + self.connect("add", self.size_adjustment) + self.tableWidth = self.allocation.width + # vbar is '1' if there is not vertical scroll bar + # if there is a vertical scroll bar, then it will have a the width of the bar + self.vbar = self.adjustScrollWindow.get_vscrollbar().allocation.width + + self.getParentAppPrefs() + self.getPrefsFactory() + + if not hasattr(self, "errorTitle"): + self.errorTitle = _("Error in Image Rename preferences") + + try: + self.prefsFactory.checkPrefsForValidity() + + except (rn.PrefValueInvalidError, rn.PrefLengthError, + rn.PrefValueKeyComboError, rn.PrefKeyError), e: + + sys.stderr.write(self.errorTitle + "\n") + sys.stderr.write(_("Sorry,these preferences contain an error:\n")) + sys.stderr.write(self.prefsFactory.formatPreferencesForPrettyPrint() + "\n") + + # the preferences were invalid + # reset them to their default + + self.prefList = self.prefsFactory.defaultPrefs + self.getPrefsFactory() + self.updateParentAppPrefs() + + msg = "%s.\n" % e + msg += _("Resetting to default values.") + sys.stderr.write(msg) + + + misc.run_dialog(self.errorTitle, msg, + parentApp, + gtk.MESSAGE_ERROR) + + for row in self.prefsFactory.getWidgetsBasedOnPreferences(): + self.append(row) + + + + + def updatePreferences(self): + prefList = [] + for row in self.pm_rows: + for col in range(self.pm_noColumns): + widget = row[col] + if widget: + name = widget.get_name() + if name == 'GtkComboBox': + value = widget.get_active_text() + elif name == 'GtkEntry': + value = widget.get_text() + else: + sys.stderr.write("Program error: Unknown preference widget!") + value = '' + else: + value = '' + prefList.append(value) + + self.prefList = prefList + self.updateParentAppPrefs() + self.prefsFactory.prefList = prefList + self.updateExample() + + + def size_adjustment(self, arg1, arg2): + """ Adjust scrolledwindow width in preferences dialog to reflect width of image rename table + + The algorithm is complicated by the need to tak into account the presence of a vertical scrollbar""" + + if self.adjustScrollWindow: + if self.adjustScrollWindow.get_vscrollbar().allocation.width > 1: + extra = self.adjustScrollWindow.get_vscrollbar().allocation.width + 10 + else: + extra = 0 + if self.vbar <= 1: + if self.allocation.width > self.tableWidth: + self.adjustScrollWindow.set_size_request(self.allocation.width + extra, -1) + self.tableWidth = self.allocation.width + extra + elif self.allocation.width - extra > self.tableWidth: + self.adjustScrollWindow.set_size_request(self.allocation.width + extra, -1) + self.tableWidth = self.allocation.width + extra + self.vbar = self.adjustScrollWindow.get_vscrollbar().allocation.width + + def getParentAppPrefs(self): + self.prefList = self.parentApp.prefs.image_rename + + + + + def getPrefsFactory(self): + self.prefsFactory = rn.ImageRenamePreferences(self.prefList, self, + sequences = sequences) + + def updateParentAppPrefs(self): + self.parentApp.prefs.image_rename = self.prefList + + def updateExample(self): + self.parentApp.updateImageRenameExample() + + def getDefaultRow(self): + return self.prefsFactory.getDefaultRow() + + def on_combobox_changed(self, widget, rowPosition): + + for col in range(self.pm_noColumns): + if self.pm_rows[rowPosition][col] == widget: + break + selection = [] + for i in range(col + 1): + # ensure it is a combo box we are getting the value from + w = self.pm_rows[rowPosition][i] + name = w.get_name() + if name == 'GtkComboBox': + selection.append(w.get_active_text()) + else: + selection.append(w.get_text()) + + for i in range(col + 1, self.pm_noColumns): + selection.append('') + + if col <> (self.pm_noColumns - 1): + widgets = self.prefsFactory.getWidgetsBasedOnUserSelection(selection) + + for i in range(col + 1, self.pm_noColumns): + oldWidget = self.pm_rows[rowPosition][i] + if oldWidget: + self.remove(oldWidget) + if oldWidget in self.pm_callbacks: + del self.pm_callbacks[oldWidget] + newWidget = widgets[i] + self.pm_rows[rowPosition][i] = newWidget + if newWidget: + self._createCallback(newWidget, rowPosition) + self.attach(newWidget, i, i+1, rowPosition, rowPosition + 1) + newWidget.show() + self.updatePreferences() + + + def on_entry_changed(self, widget, rowPosition): + self.updatePreferences() + + def on_rowAdded(self, rowPosition): + """ + Update preferences, as a row has been added + """ + self.updatePreferences() + + # if this was the last row or 2nd to last row, and another has just been added, move vertical scrollbar down + if rowPosition in range(self.pm_noRows - 3, self.pm_noRows - 2): + adjustment = self.parentApp.rename_scrolledwindow.get_vadjustment() + adjustment.set_value(adjustment.upper) + + + def on_rowDeleted(self, rowPosition): + """ + Update preferences, as a row has been deleted + """ + self.updatePreferences() + +class SubfolderTable(ImageRenameTable): + def __init__(self, parentApp, adjustScollWindow): + self.errorTitle = _("Error in Download Subfolder preferences") + ImageRenameTable.__init__(self, parentApp, adjustScollWindow) + + def getParentAppPrefs(self): + self.prefList = self.parentApp.prefs.subfolder + + def getPrefsFactory(self): + self.prefsFactory = rn.SubfolderPreferences(self.prefList, self) + + def updateParentAppPrefs(self): + self.parentApp.prefs.subfolder = self.prefList + + def updateExample(self): + self.parentApp.updateDownloadFolderExample() + + +class PreferencesDialog(gnomeglade.Component): + def __init__(self, parentApp): + gnomeglade.Component.__init__(self, + paths.share_dir(config.GLADE_FILE), + "preferencesdialog") + + self.widget.set_transient_for(parentApp.widget) + self.prefs = parentApp.prefs + + self._setupTabSelector() + + self._setupControlSpacing() + + # get example image data + + try: + w = workers.firstWorkerReadyToDownload() + root, self.sampleImageName = w.firstImage() + image = os.path.join(root, self.sampleImageName) + self.sampleImage = metadata.MetaData(image) + self.sampleImage.readMetadata() + except: + self.sampleImage = metadata.DummyMetaData() + self.sampleImageName = 'IMG_0524.CR2' + + # setup tabs + self._setupDownloadFolderTab() + self._setupImageRenameTab() + self._setupRenameOptionsTab() + self._setupDeviceTab() + self._setupBackupTab() + self._setupAutomationTab() + self._setupErrorTab() + + self.widget.realize() + + #set the width of the left column for selecting values + #note: this must be called after self.widget.realize(), or else the width calculation will fail + width_of_widest_sel_row = self.treeview.get_background_area(1, self.treeview_column)[2] + self.scrolled_window.set_size_request(width_of_widest_sel_row + 2, -1) + + #set the minimum width of the scolled window holding the image rename table + if self.rename_scrolledwindow.get_vscrollbar(): + extra = self.rename_scrolledwindow.get_vscrollbar().allocation.width + 10 + else: + extra = 10 + self.rename_scrolledwindow.set_size_request(self.rename_table.allocation.width + extra, -1) + + self.widget.show() + + def on_preferencesdialog_destroy(self, widget): + """ Delete variables from memory that cause a file descriptor to be created on a mounted media""" + del self.sampleImage, self.rename_table.prefsFactory, self.subfolder_table.prefsFactory + + def _setupTabSelector(self): + self.notebook.set_show_tabs(0) + self.model = gtk.ListStore(type("")) + column = gtk.TreeViewColumn() + rentext = gtk.CellRendererText() + column.pack_start(rentext, expand=0) + column.set_attributes(rentext, text=0) + self.treeview_column = column + self.treeview.append_column(column) + self.treeview.props.model = self.model + for c in self.notebook.get_children(): + label = self.notebook.get_tab_label(c).get_text() + if not label.startswith("_"): + self.model.append( (label,) ) + + + # select the first value in the list store + self.treeview.set_cursor(0,column) + + def on_download_folder_filechooser_button_selection_changed(self, widget): + self.prefs.download_folder = widget.get_current_folder() + self.updateDownloadFolderExample() + + def on_backup_folder_filechooser_button_selection_changed(self, widget): + self.prefs.backup_location = widget.get_current_folder() + self.updateBackupExample() + + def on_device_location_filechooser_button_selection_changed(self, widget): + self.prefs.device_location = widget.get_current_folder() + + def _setupControlSpacing(self): + """ + set spacing of some but not all controls + + not currently used + """ + + self._setupTableSpacing(self.download_folder_table) + self.download_folder_table.set_row_spacing(2, + hd.VERTICAL_CONTROL_SPACE) + self._setupTableSpacing(self.rename_example_table) + self.devices_table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) + + self._setupTableSpacing(self.backup_table) + self.backup_table.set_col_spacing(1, hd.NESTED_CONTROLS_SPACE) + self.backup_table.set_col_spacing(2, hd.CONTROL_LABEL_SPACE) + self._setupTableSpacing(self.compatibility_table) + self.compatibility_table.set_row_spacing(0, + hd.VERTICAL_CONTROL_LABEL_SPACE) + self._setupTableSpacing(self.error_table) + self.error_table.set_row_spacing(5, hd.VERTICAL_CONTROL_SPACE / 2) + + + def _setupTableSpacing(self, table): + table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) + table.set_col_spacing(1, hd.CONTROL_LABEL_SPACE) + + def _setupSubfolderTable(self): + self.subfolder_table = SubfolderTable(self, None) + self.subfolder_vbox.pack_start(self.subfolder_table) + self.subfolder_table.show_all() + + def _setupDownloadFolderTab(self): + self.download_folder_filechooser_button = gtk.FileChooserButton( + _("Select a folder to download photos to")) + self.download_folder_filechooser_button.set_current_folder( + self.prefs.download_folder) + self.download_folder_filechooser_button.set_action( + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + self.download_folder_filechooser_button.connect("selection-changed", + self.on_download_folder_filechooser_button_selection_changed) + + self.download_folder_table.attach( + self.download_folder_filechooser_button, + 2, 3, 2, 3, yoptions = gtk.SHRINK) + self.download_folder_filechooser_button.show() + + self._setupSubfolderTable() + self.updateDownloadFolderExample() + + def _setupImageRenameTab(self): + + self.rename_table = ImageRenameTable(self, self.rename_scrolledwindow) + self.rename_table_vbox.pack_start(self.rename_table) + self.rename_table.show_all() + self.original_name_label.set_markup("<i>%s</i>" % self.sampleImageName) + self.updateImageRenameExample() + + def _setupRenameOptionsTab(self): + self.downloads_today_entry = ValidatedEntry.ValidatedEntry(ValidatedEntry.bounded(ValidatedEntry.v_int, int, 0)) + self.stored_number_entry = ValidatedEntry.ValidatedEntry(ValidatedEntry.bounded(ValidatedEntry.v_int, int, 1)) + self.downloads_today_entry.connect('changed', self.on_downloads_today_entry_changed) + self.stored_number_entry.connect('changed', self.on_stored_number_entry_changed) + v = self.prefs.getAndMaybeResetDownloadsToday() + self.downloads_today_entry.set_text(str(v)) + # make the displayed value of stored sequence no 1 more than actual value + # so as not to confuse the user + self.stored_number_entry.set_text(str(self.prefs.stored_sequence_no+1)) + self.sequence_vbox.pack_start(self.downloads_today_entry, expand=True, fill=True) + self.sequence_vbox.pack_start(self.stored_number_entry, expand=False) + self.downloads_today_entry.show() + self.stored_number_entry.show() + hour, minute = self.prefs.getDayStart() + self.hour_spinbutton.set_value(float(hour)) + self.minute_spinbutton.set_value(float(minute)) + + self.strip_characters_checkbutton.set_active( + self.prefs.strip_characters) + + def _setupDeviceTab(self): + self.device_location_filechooser_button = gtk.FileChooserButton( + _("Select an image folder")) + self.device_location_filechooser_button.set_current_folder( + self.prefs.device_location) + self.device_location_filechooser_button.set_action( + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + + self.device_location_filechooser_button.connect("selection-changed", + self.on_device_location_filechooser_button_selection_changed) + + self.devices2_table.attach(self.device_location_filechooser_button, + 1, 2, 1, 2, xoptions = gtk.EXPAND|gtk.FILL, yoptions = gtk.SHRINK) + self.device_location_filechooser_button.show() + self.autodetect_device_checkbutton.set_active( + self.prefs.device_autodetection) + self.autodetect_psd_checkbutton.set_active( + self.prefs.device_autodetection_psd) + + self.updateDeviceControls() + + + def _setupBackupTab(self): + self.backup_folder_filechooser_button = gtk.FileChooserButton( + _("Select a folder in which to backup images")) + self.backup_folder_filechooser_button.set_current_folder( + self.prefs.backup_location) + self.backup_folder_filechooser_button.set_action( + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + self.backup_folder_filechooser_button.connect("selection-changed", + self.on_backup_folder_filechooser_button_selection_changed) + self.backup_table.attach(self.backup_folder_filechooser_button, + 3, 4, 7, 8, yoptions = gtk.SHRINK) + self.backup_folder_filechooser_button.show() + self.backup_identifier_entry.set_text(self.prefs.backup_identifier) + + #setup controls for manipulating sensitivity + self._backupControls0 = [self.auto_detect_backup_checkbutton, + self.missing_backup_label, + self.backup_error_radiobutton, + self.backup_warning_radiobutton, + self.backup_ignore_radiobutton] + self._backupControls1 = [self.backup_identifier_explanation_label, + self.backup_identifier_label, + self.backup_identifier_entry, + self.example_backup_path_label, + self.backup_example_label,] + self._backupControls2 = [self.backup_location_label, + self.backup_folder_filechooser_button, + self.backup_location_explanation_label] + self._backupControls = self._backupControls0 + self._backupControls1 + \ + self._backupControls2 + + #assign values to checkbuttons only when other controls + #have been setup, because their toggle signal is activated + #when a value is assigned + + self.backup_checkbutton.set_active(self.prefs.backup_images) + self.auto_detect_backup_checkbutton.set_active( + self.prefs.backup_device_autodetection) + self.updateBackupControls() + self.updateBackupExample() + + def _setupAutomationTab(self): + self.auto_startup_checkbutton.set_active( + self.prefs.auto_download_at_startup) + self.auto_insertion_checkbutton.set_active( + self.prefs.auto_download_upon_device_insertion) + self.auto_unmount_checkbutton.set_active( + self.prefs.auto_unmount) + self.auto_exit_checkbutton.set_active( + self.prefs.auto_exit) + + + def _setupErrorTab(self): + self.indicate_download_error_checkbutton.set_active( + self.prefs.indicate_download_error) + + if self.prefs.download_conflict_resolution == config.SKIP_DOWNLOAD: + self.skip_download_radiobutton.set_active(True) + else: + self.add_identifier_radiobutton.set_active(True) + + if self.prefs.backup_missing == config.REPORT_ERROR: + self.backup_error_radiobutton.set_active(True) + elif self.prefs.backup_missing == config.REPORT_WARNING: + self.backup_warning_radiobutton.set_active(True) + else: + self.backup_ignore_radiobutton.set_active(True) + + if self.prefs.backup_duplicate_overwrite: + self.backup_duplicate_overwrite_radiobutton.set_active(True) + else: + self.backup_duplicate_skip_radiobutton.set_active(True) + + def updateImageRenameExample(self): + """ + Displays example image name to the user + """ + + if hasattr(self, 'rename_table'): + name, problem = self.rename_table.prefsFactory.generateNameUsingPreferences( + self.sampleImage, self.sampleImageName, + self.prefs.strip_characters, sequencesPreliminary=False) + else: + name = problem = '' + + # since this is markup, escape it + text = "<i>%s</i>" % common.escape(name) + + if problem: + text += "\n" + # Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees + text += _("<i><b>Warning:</b> There is insufficient image metatdata to fully generate the name. Please use other renaming options.</i>") + + self.new_name_label.set_markup(text) + + def updateDownloadFolderExample(self): + """ + Displays example subfolder name(s) to the user + """ + + if hasattr(self, 'subfolder_table'): + path, problem = self.subfolder_table.prefsFactory.generateNameUsingPreferences( + self.sampleImage, self.sampleImageName, + self.prefs.strip_characters) + else: + path = problem = '' + + text = os.path.join(self.prefs.download_folder, path) + # since this is markup, escape it + path = common.escape(text) + if problem: + warning = _("<i><b>Warning:</b> There is insufficient image metatdata to fully generate subfolders. Please use other subfolder naming options.</i>" ) + else: + warning = "" + # Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see + self.example_download_path_label.set_markup(_("<i>Example: %s</i>") % text) + self.subfolder_warning_label.set_markup(warning) + + def on_hour_spinbutton_value_changed(self, spinbutton): + hour = spinbutton.get_value_as_int() + minute = self.minute_spinbutton.get_value_as_int() + self.prefs.setDayStart(hour, minute) + self.on_downloads_today_entry_changed(self.downloads_today_entry) + + def on_minute_spinbutton_value_changed(self, spinbutton): + hour = self.hour_spinbutton.get_value_as_int() + minute = spinbutton.get_value_as_int() + self.prefs.setDayStart(hour, minute) + self.on_downloads_today_entry_changed(self.downloads_today_entry) + + def on_downloads_today_entry_changed(self, entry): + if workers.noRunningWorkers() == 0: + # do not update value if a download is occurring - it will mess it up! + v = entry.get_text() + try: + v = int(v) + except: + v = 0 + if v < 0: + v = 0 + self.prefs.resetDownloadsToday(v) + sequences.setDownloadsToday(v) + self.updateImageRenameExample() + + def on_stored_number_entry_changed(self, entry): + if workers.noRunningWorkers() == 0: + # do not update value if a download is occurring - it will mess it up! + v = entry.get_text() + try: + # the displayed value of stored sequence no 1 more than actual value + # so as not to confuse the user + v = int(v) - 1 + except: + v = 0 + if v < 0: + v = 0 + self.prefs.stored_sequence_no = v + sequences.setStoredSequenceNo(v) + self.updateImageRenameExample() + + def on_response(self, dialog, arg): + if arg == gtk.RESPONSE_HELP: + webbrowser.open("http://www.damonlynch.net/rapid/documentation") + else: + # arg==gtk.RESPONSE_CLOSE, or the user hit the 'x' to close the window + self.prefs.backup_identifier = self.backup_identifier_entry.get_property("text") + + #check subfolder preferences for bad values + filtered, prefList = rn.filterSubfolderPreferences(self.prefs.subfolder) + if filtered: + cmd_line(_("The subfolder preferences had some unnecessary values removed.")) + if prefList: + self.prefs.subfolder = prefList + else: + #Preferences list is now empty + msg = _("The subfolder preferences entered are invalid and cannot be used.\nThey will be reset to their default values.") + sys.stderr.write(msg + "\n") + misc.run_dialog(PROGRAM_NAME, msg) + self.prefs.subfolder = self.prefs.get_default("subfolder") + + self.widget.destroy() + + + def on_auto_startup_checkbutton_toggled(self, checkbutton): + self.prefs.auto_download_at_startup = checkbutton.get_active() + + def on_auto_insertion_checkbutton_toggled(self, checkbutton): + self.prefs.auto_download_upon_device_insertion = checkbutton.get_active() + + def on_auto_unmount_checkbutton_toggled(self, checkbutton): + self.prefs.auto_unmount = checkbutton.get_active() + + def on_auto_exit_checkbutton_toggled(self, checkbutton): + self.prefs.auto_exit = checkbutton.get_active() + + def on_autodetect_device_checkbutton_toggled(self, checkbutton): + self.prefs.device_autodetection = checkbutton.get_active() + self.updateDeviceControls() + + def on_autodetect_psd_checkbutton_toggled(self, checkbutton): + self.prefs.device_autodetection_psd = checkbutton.get_active() + + def on_backup_duplicate_overwrite_radiobutton_toggled(self, widget): + self.prefs.backup_duplicate_overwrite = widget.get_active() + + def on_backup_duplicate_skip_radiobutton_toggled(self, widget): + self.prefs.backup_duplicate_overwrite = not widget.get_active() + + def on_backup_error_radiobutton_toggled(self, widget): + self.prefs.backup_missing = config.REPORT_ERROR + + def on_backup_warning_radiobutton_toggled(self, widget): + self.prefs.backup_missing = config.REPORT_WARNING + + def on_backup_ignore_radiobutton_toggled(self, widget): + self.prefs.backup_missing = config.IGNORE + + def on_treeview_cursor_changed(self, tree): + path, column = tree.get_cursor() + self.notebook.set_current_page(path[0]) + + + def on_strip_characters_checkbutton_toggled(self, check_button): + self.prefs.strip_characters = check_button.get_active() + self.updateImageRenameExample() + self.updateDownloadFolderExample() + + def on_indicate_download_error_checkbutton_toggled(self, check_button): + self.prefs.indicate_download_error = check_button.get_active() + + def on_add_identifier_radiobutton_toggled(self, widget): + if widget.get_active(): + self.prefs.download_conflict_resolution = config.ADD_UNIQUE_IDENTIFIER + else: + self.prefs.download_conflict_resolution = config.SKIP_DOWNLOAD + + + def updateDeviceControls(self): + """ + Sets sensitivity of image device controls + """ + controls = [self.device_location_explanation_label, + self.device_location_label, + self.device_location_filechooser_button] + + if self.prefs.device_autodetection: + for c in controls: + c.set_sensitive(False) + self.autodetect_psd_checkbutton.set_sensitive(True) + self.autodetect_image_devices_label.set_sensitive(True) + else: + for c in controls: + c.set_sensitive(True) + self.autodetect_psd_checkbutton.set_sensitive(False) + self.autodetect_image_devices_label.set_sensitive(False) + + def updateBackupControls(self): + """ + Sets sensitivity of backup related widgets + """ + + if not self.backup_checkbutton.get_active(): + for c in self._backupControls: + c.set_sensitive(False) + + else: + for c in self._backupControls0: + c.set_sensitive(True) + + self.updateBackupControlsAuto() + + def updateBackupControlsAuto(self): + """ + Sets sensitivity of subset of backup related widgets + """ + + if self.auto_detect_backup_checkbutton.get_active(): + for c in self._backupControls1: + c.set_sensitive(True) + for c in self._backupControls2: + c.set_sensitive(False) + else: + for c in self._backupControls1: + c.set_sensitive(False) + for c in self._backupControls2: + c.set_sensitive(True) + + def on_auto_detect_backup_checkbutton_toggled(self, widget): + self.prefs.backup_device_autodetection = widget.get_active() + self.updateBackupControlsAuto() + + def on_backup_checkbutton_toggled(self, widget): + self.prefs.backup_images = self.backup_checkbutton.get_active() + self.updateBackupControls() + + def on_backup_identifier_entry_changed(self, widget): + self.updateBackupExample() + + def on_backup_scan_folder_on_entry_changed(self, widget): + self.updateBackupExample() + + def updateBackupExample(self): + # Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. + path = os.path.join(config.MEDIA_LOCATION, _("externaldrive1")) + # Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. + path2 = os.path.join(config.MEDIA_LOCATION, _("externaldrive2")) + + path = os.path.join(path, self.backup_identifier_entry.get_text()) + path2 = os.path.join(path2, self.backup_identifier_entry.get_text()) + path = common.escape(path) + path2 = common.escape(path2) + self.example_backup_path_label.set_markup("<i>%s</i>\n<i>%s</i>" % (path, + path2)) + + + + +class CopyPhotos(Thread): + """Copies photos from source to destination, backing up if needed""" + def __init__(self, thread_id, parentApp, fileRenameLock, fileSequenceLock, statsLock, downloadStats, autoStart = False, cardMedia = None): + self.parentApp = parentApp + self.thread_id = thread_id + self.ctrl = True + self.running = False + self.manuallyDisabled = False + # enable the capacity to block oneself with a lock + # the lock will be first set when the thread begins + # it will then be locked when the thread needs to be paused + # releasing it will cause the code to restart from where it + # left off + self.lock = Lock() + + self.fileRenameLock = fileRenameLock + self.fileSequenceLock = fileSequenceLock + self.statsLock = statsLock + + self.downloadStats = downloadStats + + self.hasStarted = False + self.doNotStart = False + + self.autoStart = autoStart + self.cardMedia = cardMedia + + self.initializeDisplay(thread_id, self.cardMedia) + + self.noErrors = self.noWarnings = 0 + + self.scanComplete = self.downloadStarted = self.downloadComplete = False + + Thread.__init__(self) + + + def initializeDisplay(self, thread_id, cardMedia = None): + + if self.cardMedia: + media_collection_treeview.addCard(thread_id, self.cardMedia.prettyName(), + '', 0, progress=0.0, + # This refers to when a device like a hard drive is having its contents scanned, + # looking for images. It is visible initially in the progress bar for each device + # (which normally holds "x of y images copied"). + # It maybe displayed only briefly if the contents of the device being scanned is small. + progressBarText=_('scanning...')) + + + def firstImage(self): + """ + returns name, path and size of the first image + """ + name, root, size, modificationTime = self.cardMedia.firstImage() + return root, name + + def handlePreferencesError(self, e, prefsFactory): + sys.stderr.write(_("Sorry,these preferences contain an error:\n")) + sys.stderr.write(prefsFactory.formatPreferencesForPrettyPrint() + "\n") + msg = str(e) + sys.stderr.write(msg + "\n") + + def initializeFromPrefs(self, notifyOnError): + """ + Setup thread so that user preferences are handled + """ + self.prefs = self.parentApp.prefs + + self.imageRenamePrefsFactory = rn.ImageRenamePreferences(self.prefs.image_rename, self, + self.fileSequenceLock, sequences) + try: + self.imageRenamePrefsFactory.checkPrefsForValidity() + except (rn.PrefValueInvalidError, rn.PrefLengthError, + rn.PrefValueKeyComboError, rn.PrefKeyError), e: + if notifyOnError: + self.handlePreferencesError(e, self.imageRenamePrefsFactory) + raise rn.PrefError + + + self.subfolderPrefsFactory = rn.SubfolderPreferences( + self.prefs.subfolder, self) + try: + self.subfolderPrefsFactory.checkPrefsForValidity() + except (rn.PrefValueInvalidError, rn.PrefLengthError, + rn.PrefValueKeyComboError, rn.PrefKeyError), e: + if notifyOnError: + self.handlePreferencesError(e, self.subfolderPrefsFactory) + raise rn.PrefError + + # copy this variable, as it is used heavily in the loop + # and it is perhaps relatively expensive to read + self.stripCharacters = self.prefs.strip_characters + + + def run(self): + """ + Copy photos from device to local drive, and if requested, backup + + 1. Should the image be downloaded? + 1.a generate file name + 1.a.1 generate sequence numbers if needed + 1.a.2 FIFO queue sequence numbers to indicate that they could + potentially be used in a filename + 1.b check to see if a file exists with the same name in the place it will + be downloaded to + 1.c if it exisits, and unique identifiers are not being used: + 1.b.1 if using sequence numbers or letters, then potentially any of the + sequence numbers in the queue could be used to make the filename + 1.b.1.a generate and check each filename using sequence numbers in the queue + 1.b.1.b if one of these filenames is unique, then image needs to be downloaded + 1.b.2 do not do not download + + + 2. Download the image + 2.a copy it to temporary folder (this takes time) + 2.b is the file name still unique? Perhaps a new file was created with this name in the meantime + (either by another thread or another program) + 2.b.1 don't allow any other thread to rename a file + 2.b.2 check file name + 2.b.3 adding suffix if it is not unique, being careful not to overwrite any existing file with a suffix + 2.b.4 rename it to the "real"" name, effectively performing a mv + 2.b.5 allow other threads to rename files + + 3. Backup the image, using the same filename as was used when it was downloaded + 3.a does a file with the same name already exist on the backup medium? + 3.b if so, user preferences determine whether it should be overwritten or not + """ + + def getPrefs(notifyOnError): + try: + self.initializeFromPrefs(notifyOnError) + return True + except rn.PrefError: + if notifyOnError: + display_queue.put((media_collection_treeview.removeCard, (self.thread_id, ))) + msg = _("There is an error in the program preferences.") + msg += _("\nPlease check preferences, restart the program, and try again.") + logError(config.CRITICAL_ERROR, _("Download cannot proceed"), msg) + cmd_line(_("Download cannot proceed")) + cmd_line(msg) + return False + def scanMedia(): + + images = [] + imageSizeSum = 0 + for root, dirs, files in os.walk(self.cardMedia.getPath()): + for name in files: + if not self.running: + self.lock.acquire() + self.running = True + + if not self.ctrl: + self.running = False + display_queue.put((media_collection_treeview.removeCard, (self.thread_id, ))) + display_queue.close("rw") + return + + if media.isImage(name): + image = os.path.join(root, name) + size = os.path.getsize(image) + modificationTime = os.path.getmtime(image) + images.append((name, root, size, modificationTime),) + imageSizeSum += size + images.sort(key=operator.itemgetter(3)) + noImages = len(images) + + self.scanComplete = True + + if noImages: + self.cardMedia.setMedia(images, imageSizeSum, noImages) + # Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary. + # It refers to the actual number of images that can be copied. For example, the user might see the following: + # '0 of 512 images copied'. + # This particular text is displayed to the user before the download has started. + display = _("0 of %s images copied") % noImages + display_queue.put((media_collection_treeview.updateCard, (self.thread_id, self.cardMedia.sizeOfImages(), noImages))) + display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, 0.0, display, 0))) + display_queue.put((self.parentApp.timeRemaining.add, (self.thread_id, imageSizeSum))) + display_queue.put((self.parentApp.setDownloadButtonSensitivity, ())) + + # Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s. + # This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed + # to the user when they run the program, signifying the number of images found, and the device they were found on. + # %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should + # not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around + # in a sentence, but you should never modify them or leave them out. + cmd_line(_("Device scan complete: found %(number)s images on %(device)s") % + {'number': noImages, 'device': self.cardMedia.prettyName(limit=0)}) + return True + else: + # it might be better to display "0 of 0" here + display_queue.put((media_collection_treeview.removeCard, (self.thread_id, ))) + cmd_line(_("Device scan complete: no images found on %s") % self.cardMedia.prettyName(limit=0)) + return False + + def cleanUp(): + """ + Cleanup functions that must be performed whether the thread exits + early or when it has completed its run. + """ + + # possibly delete any lingering files + tf = os.listdir(tempWorkingDir) + if tf: + for f in tf: + os.remove(os.path.join(tempWorkingDir, f)) + + os.rmdir(tempWorkingDir) + + + def logError(severity, problem, details, resolution=None): + display_queue.put((log_dialog.addMessage, (self.thread_id, severity, problem, details, + resolution))) + if severity == config.WARNING: + self.noWarnings += 1 + else: + self.noErrors += 1 + + + def checkProblemWithImageNameGeneration(newName, image, problem): + if not newName: + # a serious problem - a filename should never be blank! + logError(config.SERIOUS_ERROR, + _("Image filename could not be generated"), + # '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out + _("Source: %(source)s\nProblem: %(problem)s") % {'source': image, 'problem': problem}, + IMAGE_SKIPPED) + elif problem: + logError(config.WARNING, + _("Image filename could not be properly generated. Check to ensure there is sufficient image metadata."), + _("Source: %(source)s\nDestination: %(destination)s\nProblem: %(problem)s") % + {'source': image, 'destination': newName, 'problem': problem}) + + def generateSubfolderAndFileName(image, name, needMetaDataToCreateUniqueImageName, + needMetaDataToCreateUniqueSubfolderName): + skipImage = False + try: + imageMetadata = metadata.MetaData(image) + except IOError: + logError(config.CRITICAL_ERROR, _("Could not open image"), + _("Source: %s") % image, + IMAGE_SKIPPED) + skipImage = True + imageMetadata = newName = newFile = path = subfolder = None + else: + imageMetadata.readMetadata() + if not imageMetadata.exifKeys() and (needMetaDataToCreateUniqueSubfolderName or + (needMetaDataToCreateUniqueImageName and + not addUniqueIdentifier)): + logError(config.SERIOUS_ERROR, _("Image has no metadata"), + _("Metadata is essential for generating subfolders / image names.\nSource: %s") % image, + IMAGE_SKIPPED) + skipImage = True + newName = newFile = path = subfolder = None + + else: + subfolder, problem = self.subfolderPrefsFactory.generateNameUsingPreferences( + imageMetadata, name, + self.stripCharacters) + + if problem: + logError(config.WARNING, + _("Subfolder name could not be properly generated. Check to ensure there is sufficient image metadata."), + _("Subfolder: %(subfolder)s\nImage: %(image)s\nProblem: %(problem)s") % + {'subfolder': subfolder, 'image': image, 'problem': problem}) + + # pass the subfolder the image will go into, as this is needed to determine subfolder sequence numbers + # indicate that sequences chosen should be queued + + newName, problem = self.imageRenamePrefsFactory.generateNameUsingPreferences( + imageMetadata, name, self.stripCharacters, subfolder, + sequencesPreliminary = True) + + path = os.path.join(baseDownloadDir, subfolder) + newFile = os.path.join(path, newName) + + if not newName: + skipImage = True + checkProblemWithImageNameGeneration(newName, image, problem) + + return (skipImage, imageMetadata, newName, newFile, path, subfolder) + + def downloadImage(path, newFile, newName, originalName, image, imageMetadata, subfolder): + try: + imageDownloaded = False + if not os.path.isdir(path): + os.makedirs(path) + + nameUniqueBeforeCopy = True + downloadNonUniqueFile = True + + + # do a preliminary check to see if a file with the same name already exists + if os.path.exists(newFile): + nameUniqueBeforeCopy = False + if not addUniqueIdentifier: + downloadNonUniqueFile = False + if usesSequenceElements: + # potentially, a unique image name could still be generated + # investigate this possibility + with self.fileSequenceLock: + for possibleName, problem in self.imageRenamePrefsFactory.generateNameSequencePossibilities(imageMetadata, + originalName, self.stripCharacters, subfolder): +# print "checking", possibleName, "using", originalName + if possibleName: + # no need to check for any problems here, it's just a temporary name + possibleFile = os.path.join(path, possibleName) + possibleTempFile = os.path.join(tempWorkingDir, possibleName) + if not os.path.exists(possibleFile) and not os.path.exists(possibleTempFile): + downloadNonUniqueFile = True + break + + + if self.prefs.indicate_download_error and not downloadNonUniqueFile: + logError(config.SERIOUS_ERROR, IMAGE_ALREADY_EXISTS, + _("Source: %(source)s\nDestination: %(destination)s") % + {'source': image, 'destination': newFile}, + IMAGE_SKIPPED) + + if nameUniqueBeforeCopy or downloadNonUniqueFile: + tempWorkingfile = os.path.join(tempWorkingDir, newName) + shutil.copy2(image, tempWorkingfile) + + with self.fileRenameLock: + doRename = True + if usesSequenceElements: + with self.fileSequenceLock: + # get a filename and use this as the "real" filename + newName, problem = self.imageRenamePrefsFactory.generateNameUsingPreferences( + imageMetadata, originalName, self.stripCharacters, subfolder, + sequencesPreliminary = False) + checkProblemWithImageNameGeneration(newName, image, problem) + if not newName: + # there was a serious error generating the filename + doRename = False + else: + newFile = os.path.join(path, newName) + # check if the file exists again + if os.path.exists(newFile): + if not addUniqueIdentifier: + doRename = False + if self.prefs.indicate_download_error: + logError(config.SERIOUS_ERROR, IMAGE_ALREADY_EXISTS, + _("Source: %(source)s\nDestination: %(destination)s") + % {'source': image, 'destination': newFile}, + IMAGE_SKIPPED) + else: + # add basic suffix to make the filename unique + name = os.path.splitext(newName) + suffixAlreadyUsed = True + while suffixAlreadyUsed: + if newFile in duplicate_files: + duplicate_files[newFile] += 1 + else: + duplicate_files[newFile] = 1 + identifier = '_%s' % duplicate_files[newFile] + newName = name[0] + identifier + name[1] + possibleNewFile = os.path.join(path, newName) + suffixAlreadyUsed = os.path.exists(possibleNewFile) + + if self.prefs.indicate_download_error: + logError(config.SERIOUS_ERROR, IMAGE_ALREADY_EXISTS, + _("Source: %(source)s\nDestination: %(destination)s") + % {'source': image, 'destination': newFile}, + _("Unique identifier '%s' added") % identifier) + + newFile = possibleNewFile + + + if doRename: + os.rename(tempWorkingfile, newFile) + imageDownloaded = True + if usesSequenceElements: + with self.fileSequenceLock: + self.imageRenamePrefsFactory.sequences.imageCopySucceeded() + if usesStoredSequenceNo: + self.prefs.stored_sequence_no += 1 + + with self.fileSequenceLock: + if self.prefs.incrementDownloadsToday(): + # A new day, according the user's preferences of what time a day begins, has started + cmd_line(_("New day has started - resetting 'Downloads Today' sequence number")) + + sequences.setDownloadsToday(0) + + except IOError, (errno, strerror): + logError(config.SERIOUS_ERROR, _('Download copying error'), + _("Source: %(source)s\nDestination: %(destination)s\nError: %(errorno)s %(strerror)s") + % {'source': image, 'destination': newFile, 'errorno': errno, 'strerror': strerror}, + _('The image was not copied.')) + + except OSError, (errno, strerror): + logError(config.CRITICAL_ERROR, _('Download copying error'), + "Source: %(source)s\nDestination: %(destination)s\nError: %(errorno)s %(strerror)s" + % {'source': image, 'destination': newFile, 'errorno': errno, 'strerror': strerror}, + ) + + if usesSequenceElements: + if not imageDownloaded: + self.imageRenamePrefsFactory.sequences.imageCopyFailed() + + return (imageDownloaded, newName, newFile) + + + def backupImage(subfolder, newName, imageDownloaded, newFile, image): + """ backup image to path(s) chosen by the user + + there are two scenarios: + (1) image has just been downloaded and should now be backed up + (2) image was already downloaded on some previous occassion and should still be backed up, because it hasn't been yet + (3) image has been backed up already (or at least, a file with the same name already exists) + """ + + try: + for backupDir in self.parentApp.backupVolumes: + backupPath = os.path.join(backupDir, subfolder) + newBackupFile = os.path.join(backupPath, newName) + copyBackup = True + if os.path.exists(newBackupFile): + # again, not thread safe + copyBackup = self.prefs.backup_duplicate_overwrite + if self.prefs.indicate_download_error: + severity = config.SERIOUS_ERROR + problem = _("Backup image already exists") + details = _("Source: %(source)s\nDestination: %(destination)s") \ + % {'source': image, 'destination': newBackupFile} + if copyBackup : + resolution = IMAGE_OVERWRITTEN + else: + resolution = IMAGE_SKIPPED + logError(severity, problem, details, resolution) + + if copyBackup: + if imageDownloaded: + fileToCopy = newFile + else: + fileToCopy = image + if not os.path.isdir(backupPath): + # recreate folder structure in backup location + # cannot do os.makedirs(backupPath) - it gives bad results when using external drives + # we know backupDir exists + # all the components of subfolder may not + folders = subfolder.split(os.path.sep) + folderToMake = backupDir + for f in folders: + if f: + folderToMake = os.path.join(folderToMake, f) + if not os.path.isdir(folderToMake): + try: + os.mkdir(folderToMake) + except (errno, strerror): + logError(config.SERIOUS_ERROR, _('Backing up error'), + _("Destination directory could not be created\n%(directory)s\nError: %(errno)s %(strerror)s") + % {'directory': folderToMake, 'errno': errno, 'strerror': strerror}, + ) + + shutil.copy2(fileToCopy, newBackupFile) + + except IOError, (errno, strerror): + logError(config.SERIOUS_ERROR, _('Backing up error'), + _("Source: %(source)s\nDestination: %(destination)s\nError: %(errno)s %(strerror)s") + % {'source': image, 'destination': newBackupFile, 'errno': errno, 'strerror': strerror}, + _('The image was not copied.')) + + except OSError, (errno, strerror): + logError(config.CRITICAL_ERROR, _('Backing up error'), + _("Source: %(source)s\nDestination: %(destination)s\nError: %(errno)s %(strerror)s") + % {'source': image, 'destination': newBackupFile, 'errno': errno, 'strerror': strerror} + ) + + def notifyAndUnmount(): + if not self.cardMedia.volume: + unmountMessage = "" + notificationName = PROGRAM_NAME + else: + notificationName = self.cardMedia.volume.get_name() + if self.prefs.auto_unmount: + self.cardMedia.volume.unmount(self.on_volume_unmount) + # This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it + unmountMessage = _("The device can now be safely removed") + else: + unmountMessage = "" + + message = _("%s images downloaded") % noImagesDownloaded + if noImagesSkipped: + message += "\n" + _("%s images skipped") % noImagesSkipped + + if unmountMessage: + message = "%s\n%s" % (message, unmountMessage) + + if self.noWarnings: + message = "%s\n%s " % (message, self.noWarnings) + _("warnings") + if self.noErrors: + message = "%s\n%s " % (message, self.noErrors) + _("errors") + + n = pynotify.Notification(notificationName, message) + n.show() + + + + + self.hasStarted = True + display_queue.open('w') + + #Do not try to handle any preference errors here + getPrefs(False) + + #check for presence of backup meditum + if self.prefs.backup_images: + if self.prefs.backup_missing <> config.IGNORE: + if not len(self.parentApp.backupVolumes): + if self.prefs.backup_missing == config.REPORT_ERROR: + e = config.SERIOUS_ERROR + else: + e = config.WARNING + logError(e, _("Backup device missing"), _("No backup device was detected.")) + + + if not scanMedia(): + cmd_line(_("This device has no images to download from.")) + display_queue.close("rw") + self.running = False + self.lock.release() + return + elif not self.autoStart: + # halt thread, waiting to be restarted so download proceeds + self.running = False + self.lock.acquire() + + if not self.ctrl: + # thread will restart at this point, when the program is exiting + # so must exit if self.ctrl indicates this + + self.running = False + display_queue.close("rw") + return + + self.running = True + + if not getPrefs(True): + self.running = False + display_queue.close("rw") + return + + self.downloadStarted = True + cmd_line(_("Download has started from %s") % self.cardMedia.prettyName(limit=0)) + + # Some images may not have metadata (this + # is unlikely for images straight out of a + # camera, but it is possible for images that have been edited). If + # only non-dynamic components make up the rest of an image name + # (e.g. text specified by the user), then relying on metadata will + # likely produce duplicate names. + + needMetaDataToCreateUniqueImageName = self.imageRenamePrefsFactory.needImageMetaDataToCreateUniqueName() + + # subfolder generation also need to be examined, but here the need is + # not so exacting, since subfolders contain images, and naturally the + # requirement to be unique is far more relaxed. However if subfolder + # generation relies entirely on metadata, that is a problem worth + # looking for + needMetaDataToCreateUniqueSubfolderName = self.subfolderPrefsFactory.needMetaDataToCreateUniqueName() + + i = 0 + sizeDownloaded = noImagesDownloaded = noImagesSkipped = 0 + + sizeImages = self.cardMedia.sizeOfImages(humanReadable = False) + display_queue.put((self.parentApp.addToTotalDownloadSize, (sizeImages, ))) + display_queue.put((self.parentApp.setOverallDownloadMark, ())) + display_queue.put((self.parentApp.postStartDownloadTasks, ())) + + sizeImages = float(sizeImages) + noImages = self.cardMedia.numberOfImages() + + baseDownloadDir = self.prefs.download_folder + #create a temporary directory in which to download the photos to + #don't want to put it in system temp folder, as that is likely + #to be on another partition and hence copying files from it + #to the download folder will be slow! + tempWorkingDir = tempfile.mkdtemp(prefix='rapid-tmp-', + dir=baseDownloadDir) + + IMAGE_SKIPPED = _("Image skipped") + IMAGE_OVERWRITTEN = _("Image overwritten") + IMAGE_ALREADY_EXISTS = _("Image already exists") + + addUniqueIdentifier = self.prefs.download_conflict_resolution == config.ADD_UNIQUE_IDENTIFIER + usesSequenceElements = self.imageRenamePrefsFactory.usesSequenceElements() + usesStoredSequenceNo = self.imageRenamePrefsFactory.usesTheSequenceElement(rn.STORED_SEQ_NUMBER) + sequences. setUseOfSequenceElements( + self.imageRenamePrefsFactory.usesTheSequenceElement(rn.SESSION_SEQ_NUMBER), + self.imageRenamePrefsFactory.usesTheSequenceElement(rn.SEQUENCE_LETTER)) + + + while i < noImages: + if not self.running: + self.lock.acquire() + self.running = True + + if not self.ctrl: + self.running = False + cleanUp() + display_queue.close("rw") + return + + # get information about the image to deduce image name and path + name, root, size, modificationTime = self.cardMedia.images[i] + image = os.path.join(root, name) + + skipImage, imageMetadata, newName, newFile, path, subfolder = generateSubfolderAndFileName( + image, name, needMetaDataToCreateUniqueImageName, + needMetaDataToCreateUniqueSubfolderName) + + if skipImage: + noImagesSkipped += 1 + else: + imageDownloaded, newName, newFile = downloadImage(path, newFile, newName, name, image, + imageMetadata, subfolder) + + if self.prefs.backup_images: + backupImage(subfolder, newName, imageDownloaded, newFile, image) + + if imageDownloaded: + noImagesDownloaded += 1 + else: + noImagesSkipped += 1 + try: + thumbnailType, thumbnail = imageMetadata.getThumbnailData() + except: + logError(config.WARNING, _("Image has no thumbnail"), image) + thumbnail = orientation = None + else: + orientation = imageMetadata.orientation(missing=None) + display_queue.put((image_hbox.addImage, (self.thread_id, thumbnail, orientation, image, imageDownloaded))) + + sizeDownloaded += size + percentComplete = (sizeDownloaded / sizeImages) * 100 + if sizeDownloaded == sizeImages: + self.downloadComplete = True + progressBarText = _("%(number)s of %(total)s images copied") % {'number': i + 1, 'total': noImages} + display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, percentComplete, progressBarText, size))) + + i += 1 + + with self.statsLock: + self.downloadStats.adjust(sizeDownloaded, noImagesDownloaded, noImagesSkipped, self.noWarnings, self.noErrors) + + # must manually delete these variables, or else the media cannot be unmounted (bug in pyexiv or exiv2) + del self.subfolderPrefsFactory, self.imageRenamePrefsFactory + try: + del imageMetadata + except: + pass + + notifyAndUnmount() + cmd_line(_("Download complete from %s") % self.cardMedia.prettyName(limit=0)) + display_queue.put((self.parentApp.notifyUserAllDownloadsComplete,())) + display_queue.put((self.parentApp.resetSequences,())) + + cleanUp() + display_queue.put((self.parentApp.exitOnDownloadComplete, ())) + display_queue.close("rw") + + self.running = False + if noImages: + self.lock.release() + + def startStop(self): + if self.isAlive(): + if self.running: + self.running = False + else: + try: + self.lock.release() + + except thread_error: + sys.stderr.write(self.thread_id + " thread error\n") + + def quit(self): + """ + Quits the thread + + A thread can be in one of four states: + + Not started (not alive, nothing to do) + Started and actively running (alive) + Started and paused (alive) + Completed (not alive, nothing to do) + """ + + if self.hasStarted: + if self.isAlive(): + self.ctrl = False + + if not self.running: + released = False + while not released: + try: + self.lock.release() + released = True + except thread_error: + sys.stderr.write("Could not release lock for thread %s\n" % self.thread_id) + + + + def on_volume_unmount(self, data1, data2): + """ needed for call to unmount volume""" + pass + + +class MediaTreeView(gtk.TreeView): + """ + TreeView display of memory cards and associated copying progress. + + Assumes a threaded environment. + """ + def __init__(self, parentApp): + + self.parentApp = parentApp + # card name, size of images, number of images, copy progress, copy text + self.liststore = gtk.ListStore(str, str, int, float, str) + self.mapThreadToRow = {} + + gtk.TreeView.__init__(self, self.liststore) + + self.props.enable_search = False + # make it impossible to select a row + selection = self.get_selection() + selection.set_mode(gtk.SELECTION_NONE) + + # Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. + column0 = gtk.TreeViewColumn(_("Device"), gtk.CellRendererText(), + text=0) + self.append_column(column0) + + # Size refers to the total size of images on the device, typically in MB or GB + column1 = gtk.TreeViewColumn(_("Size"), gtk.CellRendererText(), text=1) + self.append_column(column1) + + column2 = gtk.TreeViewColumn(_("Download Progress"), + gtk.CellRendererProgress(), value=3, text=4) + self.append_column(column2) + self.show_all() + + def addCard(self, thread_id, cardName, sizeImages, noImages, progress = 0.0, + progressBarText = ''): + if not progressBarText: + progressBarText = _("0 of %s images copied") % (noImages) + + # add the row, and get a temporary pointer to the row + iter = self.liststore.append((cardName, sizeImages, noImages, + progress, progressBarText)) + + self._setThreadMap(thread_id, iter) + + # adjust scrolled window height, based on row height and number of ready to start downloads + if workers.noReadyToStartWorkers() >= 1 or workers.noRunningWorkers() > 0: + # please note, at program startup, self.rowHeight() will be less than it will be when already running + # e.g. when starting with 3 cards, it could be 18, but when adding 2 cards to the already running program + # (with one card at startup), it could be 21 + height = (workers.noReadyToStartWorkers() + workers.noRunningWorkers() + 2) * (self.rowHeight()) + self.parentApp.media_collection_scrolledwindow.set_size_request(-1, height) + + + def updateCard(self, thread_id, sizeImages, noImages): + if thread_id in self.mapThreadToRow: + iter = self._getThreadMap(thread_id) + self.liststore.set_value(iter, 1, sizeImages) + self.liststore.set_value(iter, 2, noImages) + else: + sys.stderr.write("FIXME: this card is unknown") + + def removeCard(self, thread_id): + if thread_id in self.mapThreadToRow: + iter = self._getThreadMap(thread_id) + self.liststore.remove(iter) + del self.mapThreadToRow[thread_id] + + + def _setThreadMap(self, thread_id, iter): + """ + convert the temporary iter into a tree reference, which is + permanent + """ + + path = self.liststore.get_path(iter) + treerowRef = gtk.TreeRowReference(self.liststore, path) + self.mapThreadToRow[thread_id] = treerowRef + + def _getThreadMap(self, thread_id): + """ + return the tree iter for this thread + """ + + treerowRef = self.mapThreadToRow[thread_id] + path = treerowRef.get_path() + iter = self.liststore.get_iter(path) + return iter + + def updateProgress(self, thread_id, percentComplete, progressBarText, imageSize): + + iter = self._getThreadMap(thread_id) + + self.liststore.set_value(iter, 3, percentComplete) + self.liststore.set_value(iter, 4, progressBarText) + if percentComplete or imageSize: + self.parentApp.updateOverallProgress(thread_id, imageSize, percentComplete) + + + def rowHeight(self): + if not self.mapThreadToRow: + return 0 + else: + index = self.mapThreadToRow.keys()[0] + path = self.mapThreadToRow[index].get_path() + col = self.get_column(0) + return self.get_background_area(path, col)[3] + +class ImageHBox(gtk.HBox): + """ + Displays thumbnails of the images being downloaded + """ + + def __init__(self, parentApp): + gtk.HBox.__init__(self) + self.parentApp = parentApp + self.padding = hd.CONTROL_IN_TABLE_SPACE / 2 + + #create image used to lighten thumbnails + self.white = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width=100, height=100) + #fill with white + self.white.fill(0xffffffff) + + #load missing image + self.missingThumbnail = gtk.gdk.pixbuf_new_from_file_at_size(paths.share_dir('glade3/image-missing.svg'), 100, 100) + + def addImage(self, thread_id, thumbnail, orientation, filename, imageDownloaded): + """ + Add thumbnail + + Orientation indicates if the thumbnail needs to be rotated or not. + """ + + if not thumbnail: + pixbuf = self.missingThumbnail + else: + try: + pbloader = gdk.PixbufLoader() + pbloader.write(thumbnail) + # Get the resulting pixbuf and build an image to be displayed + pixbuf = pbloader.get_pixbuf() + pbloader.close() + + except: + log_dialog.addMessage(thread_id, config.WARNING, + _('Thumbnail cannot be displayed'), filename, + _('It may be corrupted')) + pixbuf = self.missingThumbnail + + if not pixbuf: + log_dialog.addMessage(thread_id, config.WARNING, + _('Thumbnail cannot be displayed'), filename, + _('It may be corrupted')) + pixbuf = self.missingThumbnail + else: + # rotate if necessary + if orientation == 8: + pixbuf = pixbuf.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE) + + # scale to size + pixbuf = common.scale2pixbuf(100, 100, pixbuf) + if not imageDownloaded: + # lighten it + self.white.composite(pixbuf, 0, 0, pixbuf.props.width, pixbuf.props.height, 0, 0, 1.0, 1.0, gtk.gdk.INTERP_HYPER, 180) + + image = gtk.Image() + image.set_from_pixbuf(pixbuf) + + self.pack_start(image, expand=False, padding=self.padding) + image.show() + + # move viewport to display the latest image + adjustment = self.parentApp.image_scrolledwindow.get_hadjustment() + adjustment.set_value(adjustment.upper) + + +class LogDialog(gnomeglade.Component): + """ + Displays a log of errors, warnings or other information to the user + """ + + def __init__(self, parentApp): + """ + Initialize values for log dialog, but do not display. + """ + + gnomeglade.Component.__init__(self, + paths.share_dir(config.GLADE_FILE), + "logdialog") + + + self.widget.connect("delete-event", self.hide_window) + + self.parentApp = parentApp + self.log_textview.set_cursor_visible(False) + self.textbuffer = self.log_textview.get_buffer() + + self.problemTag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD) + self.resolutionTag = self.textbuffer.create_tag(style=pango.STYLE_ITALIC) + + def addMessage(self, thread_id, severity, problem, details, resolution): + if severity in [config.CRITICAL_ERROR, config.SERIOUS_ERROR]: + self.parentApp.error_image.show() + elif severity == config.WARNING: + self.parentApp.warning_image.show() + + iter = self.textbuffer.get_end_iter() + self.textbuffer.insert_with_tags(iter, problem +"\n", self.problemTag) + iter = self.textbuffer.get_end_iter() + self.textbuffer.insert(iter, details + "\n") + if resolution: + iter = self.textbuffer.get_end_iter() + self.textbuffer.insert_with_tags(iter, resolution +"\n", self.resolutionTag) + + iter = self.textbuffer.get_end_iter() + self.textbuffer.insert(iter, "\n") + + # move viewport to display the latest message + adjustment = self.log_scrolledwindow.get_vadjustment() + adjustment.set_value(adjustment.upper) + + + def on_logdialog_response(self, dialog, arg): + if arg == gtk.RESPONSE_CLOSE: + pass + self.parentApp.error_image.hide() + self.parentApp.warning_image.hide() + self.parentApp.prefs.show_log_dialog = False + self.widget.hide() + return True + + def hide_window(self, window, event): + window.hide() + return True + + + +class RapidApp(gnomeglade.GnomeApp, dbus.service.Object): + def __init__(self, bus, path, name): + + dbus.service.Object.__init__ (self, bus, path, name) + self.running = False + + gladefile = paths.share_dir(config.GLADE_FILE) + + gnomeglade.GnomeApp.__init__(self, "rapid", __version__, gladefile, "rapidapp") + + + # notifications + self.displayDownloadSummaryNotification = False + self.initPyNotify() + + self.prefs = RapidPreferences() + self.prefs.notify_add(self.on_preference_changed) + + self.testing = False + if self.testing: + self.setTestingEnv() + +# sys.exit(0) + + self.widget.show() + + displayPreferences = self.checkForUpgrade(__version__) + self.prefs.program_version = __version__ + + self.timeRemaining = TimeRemaining() + self._resetDownloadInfo() + self.statusbar_context_id = self.rapid_statusbar.get_context_id("progress") + + self.error_image.hide() + self.warning_image.hide() + + if not displayPreferences: + displayPreferences = not self.checkPreferencesOnStartup() + + # display download information using threads + global media_collection_treeview, image_hbox, log_dialog + global download_queue, image_queue, log_queue + global workers + + #track files that should have a suffix added to them + global duplicate_files + + # control sequence numbers and letters + global sequences + + duplicate_files = {} + + downloadsToday = self.prefs.getAndMaybeResetDownloadsToday() + sequences = rn.Sequences(downloadsToday, self.prefs.stored_sequence_no) + + self.downloadStats = DownloadStats() + + # set the number of seconds gap with which to measure download time remaing + self.downloadTimeGap = 3 + + #locks for threadsafe file downloading and stats gathering + self.fileRenameLock = Lock() + self.fileSequenceLock = Lock() + self.statsLock = Lock() + + # log window, in dialog format + # used for displaying download information to the user + + log_dialog = LogDialog(self) + + + self.volumeMonitor = None + if self.usingVolumeMonitor(): + self.startVolumeMonitor() + + + # set up tree view display + media_collection_treeview = MediaTreeView(self) + + self.media_collection_vbox.pack_start(media_collection_treeview) + + #thumbnail display + image_hbox = ImageHBox(self) + self.image_viewport.add(image_hbox) + self.image_viewport.modify_bg(gtk.STATE_NORMAL, gdk.color_parse("white")) + self.set_display_thumbnails(self.prefs.display_thumbnails) + + self.backupVolumes = {} + + self._setupDownloadbutton() + + #status bar progress bar + self.download_progressbar = gtk.ProgressBar() + self.download_progressbar.set_size_request(150, -1) + self.download_progressbar.show() + self.download_progressbar_hbox.pack_start(self.download_progressbar, expand=False, + fill=0) + + + # menus +# self.menu_resequence.set_sensitive(False) + + self.menu_display_thumbnails.set_active(self.prefs.display_thumbnails) + self.menu_clear.set_sensitive(False) + + self.setupAvailableImageAndBackupMedia(onStartup=True, onPreferenceChange=False, doNotAllowAutoStart = displayPreferences) + + #adjust viewport size for displaying media + #this is important because the code in MediaTreeView.addCard() is inaccurate at program startup + + height = self.media_collection_viewport.size_request()[1] + self.media_collection_scrolledwindow.set_size_request(-1, height) + + self.download_button.grab_focus() + + if displayPreferences: + PreferencesDialog(self) + + + + @dbus.service.method (config.DBUS_NAME, + in_signature='', out_signature='b') + def is_running (self): + return self.running + + @dbus.service.method (config.DBUS_NAME, + in_signature='', out_signature='') + def start (self): + if self.is_running(): + self.rapidapp.present() + else: + self.running = True + self.main() + self.running = False + + def setTestingEnv(self): + self.prefs.program_version = '0.0.8~b7' + r = ['Date time', 'Image date', 'YYYYMMDD', 'Text', '-', '', 'Date time', 'Image date', 'HHMM', 'Text', '-', '', 'Session number', '1', 'Three digits', 'Text', '-iso', '', 'Metadata', 'ISO', '', 'Text', '-f', '', 'Metadata', 'Aperture', '', 'Text', '-', '', 'Metadata', 'Focal length', '', 'Text', 'mm-', '', 'Metadata', 'Exposure time', '', 'Filename', 'Extension', 'lowercase'] + self.prefs.image_rename = r + + + + def checkPreferencesOnStartup(self): + prefsOk = rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder) + if not prefsOk: + title = PROGRAM_NAME + msg = _("There is an error in the program preferences.") + msg += " " + _("Some preferences will be reset.") + sys.stderr.write(msg +'\n') +# misc.run_dialog(title, msg) + return prefsOk + + def checkForUpgrade(self, runningVersion): + """ Checks if the running version of the program is different from the version recorded in the preferences. + + If the version is different, then the preferences are checked to see whether they should be upgraded or not. + + returns True if program preferences window should be opened """ + + displayPrefs = upgraded = False + + previousVersion = self.prefs.program_version + if previousVersion: + # the program has been run previously for this user + + pv = common.pythonifyVersion(previousVersion) + rv = common.pythonifyVersion(runningVersion) + + title = PROGRAM_NAME + imageRename = subfolder = None + + if pv != rv: + if pv > rv: + prefsOk = rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder) + + msg = _("A newer version of this program was previously run on this computer.\n\n") + if prefsOk: + msg += _("Program preferences appear to be valid, but please check them to ensure correct operation.") + else: + msg += _("Sorry, some preferences are invalid and will be reset.") + sys.stderr.write(_("Warning:") + " %s\n" % msg) + misc.run_dialog(title, msg) + displayPrefs = True + + else: + cmd_line(_("This version of the program is newer than the previously run version. Checking preferences.")) +# if True: + if rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder, previousVersion): + upgraded, imageRename, subfolder = rn.upgradePreferencesToCurrent(self.prefs.image_rename, self.prefs.subfolder, previousVersion) + if upgraded: + self.prefs.image_rename = imageRename + self.prefs.subfolder = subfolder + cmd_line(_("Preferences were modified.")) + msg = _('This version of the program uses different preferences than the old version. Your preferences have been updated.\n\nPlease check them to ensure correct operation.') + misc.run_dialog(title, msg) + displayPrefs = True + else: + cmd_line(_("No preferences needed to be changed.")) + else: + msg = _('This version of the program uses different preferences than the old version. Some of your previous preferences were invalid, and could not be updated. They will be reset.') + sys.stderr.write(msg + "\n") + misc.run_dialog(title, msg) + displayPrefs = True + + return displayPrefs + + def initPyNotify(self): + if not pynotify.init("TestCaps"): + sys.stderr.write(_("Problem using pynotify.") + "\n") + sys.exit(1) + + capabilities = {'actions': False, + 'body': False, + 'body-hyperlinks': False, + 'body-images': False, + 'body-markup': False, + 'icon-multi': False, + 'icon-static': False, + 'sound': False, + 'image/svg+xml': False, + 'append': False} + + caps = pynotify.get_server_caps () + if caps is None: + sys.stderr.write(_("Failed to receive pynotify server capabilities.") + "\n") + sys.exit (1) + + for cap in caps: + capabilities[cap] = True + + info = pynotify.get_server_info() + + def usingVolumeMonitor(self): + """ + Returns True if programs needs to use gnomevfs volume monitor + """ + + return (self.prefs.device_autodetection or + (self.prefs.backup_images and + self.prefs.backup_device_autodetection + )) + + + def startVolumeMonitor(self): + if not self.volumeMonitor: + self.volumeMonitor = VMonitor(self) + + def displayBackupVolumes(self): + """ + Create a message to be displayed to the user showing which backup volumes will be used + """ + message = '' + + paths = self.backupVolumes.keys() + i = 0 + v = len(paths) + prefix = '' + for b in paths: + if v > 1: + if i < (v -1) and i > 0: + prefix = ', ' + elif i == (v - 1) : + prefix = " " + _("and") + " " + i += 1 + message = "%s%s'%s'" % (message, prefix, self.backupVolumes[b].get_name()) + + if v > 1: + message = _("Using backup devices") + " %s" % message + elif v == 1: + message = _("Using backup device") + " %s" % message + else: + message = _("No backup devices detected") + + return message + + def searchForPsd(self): + """ + Check to see if user preferences are to automatically search for Portable Storage Devices or not + """ + return self.prefs.device_autodetection_psd and self.prefs.device_autodetection + + + def isGProxyShadowMount(self, gvfsVolume): + + """ gvfs GProxyShadowMount are used for camera specific things, not the data in the memory card """ + if using_gio: + #FIXME: this is a hack, but what is the correct function? + return str(type(gvfsVolume)).find('GProxyShadowMount') >= 0 + else: + return False + + def workerHasThisPath(self, path): + havePath= False + for w in workers.getNonFinishedWorkers(): + if w.cardMedia.path == path: + havePath = True + break + return havePath + + def on_volume_mounted(self, monitor, mount): + """ + callback run when gnomevfs indicates a new volume + has been mounted + """ + + if self.usingVolumeMonitor(): + volume = Volume(mount) + path = volume.get_path() + if not self.isGProxyShadowMount(mount): + self._printDetectedDevice(volume.get_name(limit=0), path) + + isBackupVolume = self.checkIfBackupVolume(path) + + if isBackupVolume: + backupPath = os.path.join(path, self.prefs.backup_identifier) + if path not in self.backupVolumes: + self.backupVolumes[backupPath] = volume + self.rapid_statusbar.push(self.statusbar_context_id, self.displayBackupVolumes()) + + elif media.isImageMedia(path) or self.searchForPsd(): + cardMedia = CardMedia(path, volume, True) + i = workers.getNextThread_id() + + self._printAutoStart(self.prefs.auto_download_upon_device_insertion) + + workers.append(CopyPhotos(i, self, self.fileRenameLock, self.fileSequenceLock, self.statsLock, + self.downloadStats, self.prefs.auto_download_upon_device_insertion, + cardMedia)) + + + self.setDownloadButtonSensitivity() + self.startScan() + + + def on_volume_unmounted(self, monitor, volume): + """ + callback run when gnomevfs indicates a volume + has been unmounted + """ + volume = Volume(volume) + path = volume.get_path() + + # four scenarios - + # volume is waiting to be scanned + # the volume has been scanned but downloading has not yet started + # images are being downloaded from volume (it must be a messy unmount) + # images finished downloading from volume + + if path: + # first scenario + for w in workers.getReadyToStartWorkers(): + if w.cardMedia.volume == volume: + media_collection_treeview.removeCard(w.thread_id) + workers.disableWorker(w.thread_id) + # second scenario + for w in workers.getReadyToDownloadWorkers(): + if w.cardMedia.volume == volume: + media_collection_treeview.removeCard(w.thread_id) + workers.disableWorker(w.thread_id) + + # fourth scenario - nothing to do + + # remove backup volumes + backupPath = os.path.join(path, self.prefs.backup_identifier) + if backupPath in self.backupVolumes: + del self.backupVolumes[backupPath] + self.rapid_statusbar.push(self.statusbar_context_id, self.displayBackupVolumes()) + + + + def clearCompletedDownloads(self): + """ + clears the display of completed downloads + """ + + for w in workers.getFinishedWorkers(): + media_collection_treeview.removeCard(w.thread_id) + + + + + def clearNotStartedDownloads(self): + """ + Clears the display of the download and instructs the thread not to run + """ + + for w in workers.getNotDownloadingWorkers(): + media_collection_treeview.removeCard(w.thread_id) + workers.disableWorker(w.thread_id) + + def checkIfBackupVolume(self, path): + """ + Checks to see if backups are enabled and path represents a valid backup location + + Checks against user preferences. + """ + if self.prefs.backup_images: + if self.prefs.backup_device_autodetection: + if media.isBackupMedia(path, self.prefs.backup_identifier): + return True + elif path == self.prefs.backup_location: + # user manually specified the path + return True + return False + + def _printDetectedDevice(self, volume_name, path): + cmd_line (_("Detected %(device)s with path %(path)s") % {'device': volume_name, 'path': path}) + + def _printAutoStart(self, autoStart): + if autoStart: + cmd_line(_("Automatically start download is true") ) + else: + cmd_line(_("Automatically start download is false") ) + + def setupAvailableImageAndBackupMedia(self, onStartup, onPreferenceChange, doNotAllowAutoStart): + """ + Creates a list of CardMedia + + onStartup should be True if the program is still starting, i.e. this is being called from the + program's initialization. + + onPreferenceChange should be True if this is being called as the result of a preference + bring changed + + Removes any image media that are currently not downloaded, + or finished downloading + """ + + self.clearNotStartedDownloads() + + cardMediaList = [] + self.backupVolumes = {} + + if not workers.noDownloadingWorkers(): + self.downloadStats.clear() + self._resetDownloadInfo() + + if self.usingVolumeMonitor(): + # either using automatically detected backup devices + # or image devices + + for v in self.volumeMonitor.get_mounts(): + volume = Volume(v) + path = volume.get_path(avoid_gnomeVFS_bug = True) + + if path: + if not self.isGProxyShadowMount(v): + self._printDetectedDevice(volume.get_name(limit=0), path) + isBackupVolume = self.checkIfBackupVolume(path) + if isBackupVolume: + backupPath = os.path.join(path, self.prefs.backup_identifier) + self.backupVolumes[backupPath] = volume + elif self.prefs.device_autodetection and (media.isImageMedia(path) or self.searchForPsd()): + cardMediaList.append(CardMedia(path, volume, True)) + + + if not self.prefs.device_autodetection: + # user manually specified the path from which to download images + path = self.prefs.device_location + if path: + cmd_line(_("Using manually specified path") + " %s" % path) + cardMedia = CardMedia(path, None, True) + cardMediaList.append(cardMedia) + + if self.prefs.backup_images: + if not self.prefs.backup_device_autodetection: + # user manually specified backup location + self.backupVolumes[self.prefs.backup_location] = None + self.rapid_statusbar.push(self.statusbar_context_id, '') + else: + self.rapid_statusbar.push(self.statusbar_context_id, self.displayBackupVolumes()) + + else: + self.rapid_statusbar.push(self.statusbar_context_id, '') + + # add each memory card / other device to the list of threads + j = workers.getNextThread_id() + + if doNotAllowAutoStart: + autoStart = False + else: + autoStart = (not onPreferenceChange) and ((self.prefs.auto_download_at_startup and onStartup) or (self.prefs.auto_download_upon_device_insertion and not onStartup)) + + self._printAutoStart(autoStart) + + for i in range(j, j + len(cardMediaList)): + cardMedia = cardMediaList[i - j] + workers.append(CopyPhotos(i, self, self.fileRenameLock, self.fileSequenceLock, self.statsLock, + self.downloadStats, autoStart, cardMedia)) + + + self.setDownloadButtonSensitivity() + self.startScan() + + def _setupDownloadbutton(self): + + self.download_hbutton_box = gtk.HButtonBox() + self.download_button_is_download = True + self.download_button = gtk.Button() + self.download_button.set_use_underline(True) + self._set_download_button() + self.download_button.connect('clicked', self.on_download_button_clicked) + self.download_hbutton_box.set_layout(gtk.BUTTONBOX_START) + self.download_hbutton_box.pack_start(self.download_button) + self.download_hbutton_box.show_all() + self.buttons_hbox.pack_start(self.download_hbutton_box, + padding=hd.WINDOW_BORDER_SPACE) + + self.setDownloadButtonSensitivity() + + + def set_display_thumbnails(self, value): + if value: + self.image_scrolledwindow.show_all() + else: + self.image_scrolledwindow.hide() + + + def _resetDownloadInfo(self): + self.markSet = False + self.startTime = None + self.totalDownloadSize = self.totalDownloadedSoFar = 0 + self.totalDownloadSizeThisRun = self.totalDownloadedSoFarThisRun = 0 + self.timeRemaining.clear() + + def addToTotalDownloadSize(self, size): + self.totalDownloadSize += size + + def setOverallDownloadMark(self): + if not self.markSet: + self.markSet = True + self.totalDownloadSizeThisRun = self.totalDownloadSize - self.totalDownloadedSoFar + self.totalDownloadedSoFarThisRun = 0 + + self.startTime = time.time() + self.timeStatusBarUpdated = self.startTime + + self.timeMark = self.startTime + self.sizeMark = 0 + + def startOrResumeWorkers(self): + + # resume any paused workers + for w in workers.getPausedDownloadingWorkers(): + w.startStop() + self.timeRemaining.setTimeMark(w) + + #start any new workers + workers.startDownloadingWorkers() + + if is_beta and verbose: + workers.printWorkerStatus() + + + def updateOverallProgress(self, thread_id, imageSize, percentComplete): + """ + Updates progress bar and status bar text with time remaining + to download images + """ + + self.totalDownloadedSoFar += imageSize + self.totalDownloadedSoFarThisRun += imageSize + + fraction = self.totalDownloadedSoFar / float(self.totalDownloadSize) + + self.download_progressbar.set_fraction(fraction) + + if percentComplete == 100.0: + self.menu_clear.set_sensitive(True) + self.timeRemaining.remove(thread_id) + + if self.downloadComplete(): + # finished all downloads + self.rapid_statusbar.push(self.statusbar_context_id, "") + self.download_button_is_download = True + self._set_download_button() + self.setDownloadButtonSensitivity() + cmd_line(_("All downloads complete")) + if is_beta and verbose: + workers.printWorkerStatus() + + else: + now = time.time() + self.timeRemaining.update(thread_id, imageSize) + + if now > (self.downloadTimeGap + self.timeMark): + amtTime = now - self.timeMark + self.timeMark = now + amtDownloaded = self.totalDownloadedSoFarThisRun - self.sizeMark + self.sizeMark = self.totalDownloadedSoFarThisRun + amtToDownload = float(self.totalDownloadSizeThisRun) - self.totalDownloadedSoFarThisRun + downloadSpeed = "%1.1f" % (amtDownloaded / 1048576 / amtTime) +_("MB/s") + self.speed_label.set_text(downloadSpeed) + + timeRemaining = self.timeRemaining.timeRemaining() + if timeRemaining: + secs = int(timeRemaining) + + if secs == 0: + message = "" + elif secs == 1: + message = _("About 1 second remaining") + elif secs < 60: + message = _("About %i seconds remaining") % secs + elif secs == 60: + message = _("About 1 minute remaining") + else: + # Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed. + # '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount + # of time the download has remainging, e.g. 'About 5:36 minutes remaining' + message = _("About %(minutes)i:%(seconds)02i minutes remaining") % {'minutes': secs / 60, 'seconds': secs % 60} + + self.rapid_statusbar.push(self.statusbar_context_id, message) + + + def resetSequences(self): + if self.downloadComplete(): + sequences.reset(self.prefs.getDownloadsToday(), self.prefs.stored_sequence_no) + + def notifyUserAllDownloadsComplete(self): + """ Possibly notify the user all downloads are complete using libnotify + + Reset progress bar info""" + + if self.downloadComplete(): + if self.displayDownloadSummaryNotification: + message = _("All downloads complete") + message += "\n%s " % self.downloadStats.noImagesDownloaded + _("images downloaded") + if self.downloadStats.noImagesSkipped: + message = "%s\n%s " % (message, self.downloadStats.noImagesSkipped) + _("images skipped") + if self.downloadStats.noWarnings: + message = "%s\n%s " % (message, self.downloadStats.noWarnings) + _("warnings") + if self.downloadStats.noErrors: + message = "%s\n%s " % (message, self.downloadStats.noErrors) +_("errors") + n = pynotify.Notification(PROGRAM_NAME, message) + n.show() + self.displayDownloadSummaryNotification = False # don't show it again unless needed + self.downloadStats.clear() + self._resetDownloadInfo() + self.speed_label.set_text(' ') + + def exitOnDownloadComplete(self): + if self.downloadComplete(): + if self.prefs.auto_exit: + if not (self.downloadStats.noErrors or self.downloadStats.noWarnings): + self.quit() + + def downloadComplete(self): + return self.totalDownloadedSoFar == self.totalDownloadSize + + def setDownloadButtonSensitivity(self): + + isSensitive = workers.noReadyToDownloadWorkers() > 0 or workers.noDownloadingWorkers() > 0 + + if isSensitive: + self.download_button.props.sensitive = True + self.menu_download_pause.props.sensitive = True + else: + self.download_button.props.sensitive = False + self.menu_download_pause.props.sensitive = False + + return isSensitive + + + def on_rapidapp_destroy(self, widget): + """Called when the application is going to quit""" + workers.quitAllWorkers() + + self.flushevents() + + display_queue.close("w") + + + def on_menu_clear_activate(self, widget): + self.clearCompletedDownloads() + widget.set_sensitive(False) + + def on_menu_report_problem_activate(self, widget): + webbrowser.open("https://bugs.launchpad.net/rapid") + + def on_menu_get_help_online_activate(self, widget): + webbrowser.open("http://www.damonlynch.net/rapid/help.html") + + def on_menu_donate_activate(self, widget): + webbrowser.open("http://www.damonlynch.net/rapid/donate.html") + + def on_menu_translate_activate(self, widget): + webbrowser.open("http://www.damonlynch.net/rapid/translate.html") + + def on_menu_preferences_activate(self, widget): + """ Sets preferences for the application using dialog window """ + + PreferencesDialog(self) + + def on_menu_log_window_toggled(self, widget): + active = widget.get_active() + self.prefs.show_log_dialog = active + if active: + log_dialog.widget.show() + else: + log_dialog.widget.hide() + + def on_menu_display_thumbnails_toggled(self, check_button): + self.prefs.display_thumbnails = check_button.get_active() + + def on_menu_about_activate(self, widget): + """ Display about dialog box """ + + about = gtk.glade.XML(paths.share_dir(config.GLADE_FILE), "about").get_widget("about") + about.set_property("name", PROGRAM_NAME) + about.set_property("version", __version__) + about.run() + about.destroy() + + def _set_download_button(self): + """ + Sets download button to appropriate state + """ + if self.download_button_is_download: + # This text will be displayed to the user on the Download / Pause button. + # Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines + self.download_button.set_label(_("_Download ")) + self.download_button.set_image(gtk.image_new_from_stock( + gtk.STOCK_CONVERT, + gtk.ICON_SIZE_BUTTON)) + else: + # button should indicate paused state + self.download_button.set_image(gtk.image_new_from_stock( + gtk.STOCK_MEDIA_PAUSE, + gtk.ICON_SIZE_BUTTON)) + # This text will be displayed to the user on the Download / Pause button. + self.download_button.set_label(_("_Pause") + " ") + + def on_menu_download_pause_activate(self, widget): + self.on_download_button_clicked(widget) + + def startScan(self): + if workers.noReadyToStartWorkers() > 0: + workers.startWorkers() + + + + def postStartDownloadTasks(self): + if workers.noDownloadingWorkers() > 1: + self.displayDownloadSummaryNotification = True + + # set button to display Pause + self.download_button_is_download = False + self._set_download_button() + + def startDownload(self): + self.startOrResumeWorkers() + self.postStartDownloadTasks() + + def pauseDownload(self): + for w in workers.getDownloadingWorkers(): + w.startStop() + # set button to display Download + if not self.download_button_is_download: + self.download_button_is_download = True + self._set_download_button() + + def on_download_button_clicked(self, widget): + """ + Handle download button click. + + Button is in one of two states: download, or pause. + + If download, a click indicates to start or resume a download run. + If pause, a click indicates to pause all running downloads. + """ + if self.download_button_is_download: + self.startDownload() + else: + self.pauseDownload() + + def on_preference_changed(self, key, value): + + if key == 'display_thumbnails': + self.set_display_thumbnails(value) + elif key == 'show_log_dialog': + self.menu_log_window.set_active(value) + elif key in ['device_autodetection', 'device_autodetection_psd', 'backup_images', 'device_location', + 'backup_device_autodetection', 'backup_location' ]: + if self.usingVolumeMonitor(): + self.startVolumeMonitor() + cmd_line("\n" + _("Preferences were changed.")) + self.setupAvailableImageAndBackupMedia(onStartup = False, onPreferenceChange = True, doNotAllowAutoStart = False) + if is_beta and verbose: + print "Current worker status:" + workers.printWorkerStatus() + + def on_error_eventbox_button_press_event(self, widget, event): + self.prefs.show_log_dialog = True + log_dialog.widget.show() + +class VMonitor: + """ Transistion to gvfs from gnomevfs""" + def __init__(self, app): + self.app = app + if using_gio: + self.vmonitor = gio.volume_monitor_get() + self.vmonitor.connect("mount-added", self.app.on_volume_mounted) + self.vmonitor.connect("mount-removed", self.app.on_volume_unmounted) + else: + self.vmonitor = gnomevfs.VolumeMonitor() + self.vmonitor.connect("volume-mounted", self.app.on_volume_mounted) + self.vmonitor.connect("volume-unmounted", self.app.on_volume_unmounted) + + + def get_mounts(self): + if using_gio: + return self.vmonitor.get_mounts() + else: + return self.vmonitor.get_mounted_volumes() + +class Volume: + """ Transistion to gvfs from gnomevfs""" + def __init__(self, volume): + self.volume = volume + + def get_name(self, limit=config.MAX_LENGTH_DEVICE_NAME): + if using_gio: + v = self.volume.get_name() + else: + v = self.volume.get_display_name() + + if limit: + if len(v) > limit: + v = v[:limit] + '...' + return v + + def get_path(self, avoid_gnomeVFS_bug = False): + if using_gio: + path = self.volume.get_root().get_path() + else: + uri = self.volume.get_activation_uri() + path = None + if avoid_gnomeVFS_bug: + # ugly hack to work around bug where gnomevfs.get_local_path_from_uri(uri) causes a crash + mediaLocation = "file://" + config.MEDIA_LOCATION + if uri.find(mediaLocation) == 0: + path = gnomevfs.get_local_path_from_uri(uri) + else: + path = gnomevfs.get_local_path_from_uri(uri) + return path + + def unmount(self, callback): + self.volume.unmount(callback) + +class DownloadStats: + def __init__(self): + self.clear() + + def adjust(self, size, noImagesDownloaded, noImagesSkipped, noWarnings, noErrors): + self.downloadSize += size + self.noImagesDownloaded += noImagesDownloaded + self.noImagesSkipped += noImagesSkipped + self.noWarnings += noWarnings + self.noErrors += noErrors + + def clear(self): + self.noImagesDownloaded = self.noImagesSkipped = 0 + self.downloadSize = 0 + self.noWarnings = self.noErrors = 0 + +class TimeForDownload: + pass + +class TimeRemaining: + gap = 2 + def __init__(self): + self.clear() + + def add(self, w, size): + if w not in self.times: + t = TimeForDownload() + t.timeRemaining = None + t.size = size + t.downloaded = 0 + t.sizeMark = 0 + t.timeMark = time.time() + self.times[w] = t + + def update(self, w, size): + if w in self.times: + self.times[w].downloaded += size + now = time.time() + tm = self.times[w].timeMark + amtTime = now - tm + if amtTime > self.gap: + self.times[w].timeMark = now + amtDownloaded = self.times[w].downloaded - self.times[w].sizeMark + self.times[w].sizeMark = self.times[w].downloaded + timefraction = amtDownloaded / amtTime + amtToDownload = float(self.times[w].size) - self.times[w].downloaded + self.times[w].timeRemaining = amtToDownload / timefraction + + def _timeEstimates(self): + for t in self.times: + yield self.times[t].timeRemaining + + def timeRemaining(self): + return max(self._timeEstimates()) + + def setTimeMark(self, w): + if w in self.times: + self.times[w].timeMark = time.time() + + def clear(self): + self.times = {} + + def remove(self, w): + if w in self.times: + del self.times[w] + +def programStatus(): + print _("Goodbye") + + +def start (): + global is_beta + is_beta = config.version.find('~b') > 0 + + parser = OptionParser(version= "%%prog %s" % config.version) + parser.set_defaults(verbose=is_beta, extensions=False) + # Translators: this text is displayed to the user when they request information on the command line options. + # The text %default should not be modified or left out. + parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help=_("display program information on the command line as the program runs (default: %default)")) + parser.add_option("-q", "--quiet", action="store_false", dest="verbose", help=_("only output errors to the command line")) + # image file extensions are recognized RAW files plus TIFF and JPG + parser.add_option("-e", "--extensions", action="store_true", dest="extensions", help=_("list image file extensions the program recognizes and exit")) + (options, args) = parser.parse_args() + global verbose + verbose = options.verbose + + if verbose: + atexit.register(programStatus) + + if options.extensions: + exts = config.RAW_FILE_EXTENSIONS + config.NON_RAW_IMAGE_FILE_EXTENSIONS + v = '' + for e in exts[:-1]: + v += '%s, ' % e.upper() + v = v[:-1] + ' '+ (_('and %s') % exts[-1].upper()) + print v + sys.exit(0) + + if using_gio: + cmd_line(_("Using") + " GIO") + else: + # Which volume management code is being used (GIO or GnomeVFS) + cmd_line(_("Using") + " GnomeVFS") + + gdk.threads_init() + display_queue.open("rw") + tube.tube_add_watch(display_queue, updateDisplay) + gdk.threads_enter() + + # run only a single instance of the application + bus = dbus.SessionBus () + request = bus.request_name (config.DBUS_NAME, dbus.bus.NAME_FLAG_DO_NOT_QUEUE) + if request != dbus.bus.REQUEST_NAME_REPLY_EXISTS: + app = RapidApp (bus, '/', config.DBUS_NAME) + else: + # this application is already running + print _("%s is already running") % PROGRAM_NAME + object = bus.get_object (config.DBUS_NAME, "/") + app = dbus.Interface (object, config.DBUS_NAME) + + app.start() + gdk.threads_leave() + +if __name__ == "__main__": + start() diff --git a/rapid/renamesubfolderprefs.py b/rapid/renamesubfolderprefs.py new file mode 100644 index 0000000..9804c59 --- /dev/null +++ b/rapid/renamesubfolderprefs.py @@ -0,0 +1,1470 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +""" Define and test preferences for use in PlusMinus tables. + +These are displayed to the user as a series of rows in the user +preferences dialog window. + +Preferences for subfolders and image renaming are defined below +in dictionaries and lists. This makes it easier for checking validity and +creating combo boxes. + +There are 3 levels: 0, 1 and 2, which specify the depth of the pref value. +Level 0 is the topmost level, and corresponds to the first entry in the +row of preferences the user sees in the preferences dialog window. + +Custom exceptions are defined to handle invalid preferences. + +The user's actual preferences, on the other hand, are stored in flat lists. +Each list has members which are a multiple of 3 in length. +Each group of 3 members is equal to one line of preferences in the plus minus +table. +""" +#needed for python 2.5, unneeded for python 2.6 +from __future__ import with_statement + +import string + +import os +import re +import sys + +import gtk.gdk as gdk + +try: + import pygtk + pygtk.require("2.0") +except: + pass +try: + import gtk +except: + sys.exit(1) + +from common import Configi18n +global _ +_ = Configi18n._ + +import datetime + +import ValidatedEntry +import config + +from common import pythonifyVersion + +# Special key in each dictionary which specifies the order of elements. +# It is very important to have a consistent and rational order when displaying +# these prefs to the user, and dictionaries are unsorted. + +ORDER_KEY = "__order__" + +# PLEASE NOTE: these values are duplicated in a dummy class whose function +# is to have them put into the translation template. If you change the values below +# then change the value in class i18TranslateMeThanks as well!! Thanks!! + +# *** Level 0 +DATE_TIME = 'Date time' +TEXT = 'Text' +FILENAME = 'Filename' +METADATA = 'Metadata' +SEQUENCES = 'Sequences' + +SEPARATOR = os.sep + +# *** Level 1 + +# Date time +IMAGE_DATE = 'Image date' +TODAY = 'Today' +YESTERDAY = 'Yesterday' + +# File name +NAME_EXTENSION = 'Name + extension' +NAME = 'Name' +EXTENSION = 'Extension' +IMAGE_NUMBER = 'Image number' + +# Metadata +APERTURE = 'Aperture' +ISO = 'ISO' +EXPOSURE_TIME = 'Exposure time' +FOCAL_LENGTH = 'Focal length' +CAMERA_MAKE = 'Camera make' +CAMERA_MODEL = 'Camera model' +SHORT_CAMERA_MODEL = 'Short camera model' +SHORT_CAMERA_MODEL_HYPHEN = 'Hyphenated short camera model' +SERIAL_NUMBER = 'Serial number' +SHUTTER_COUNT = 'Shutter count' +OWNER_NAME = 'Owner name' + +#Image sequences +DOWNLOAD_SEQ_NUMBER = 'Downloads today' +SESSION_SEQ_NUMBER = 'Session number' +SUBFOLDER_SEQ_NUMBER = 'Subfolder number' +STORED_SEQ_NUMBER = 'Stored number' + +SEQUENCE_LETTER = 'Sequence letter' + + + +# *** Level 2 + +# Image number +IMAGE_NUMBER_ALL = 'All digits' +IMAGE_NUMBER_1 = 'Last digit' +IMAGE_NUMBER_2 = 'Last 2 digits' +IMAGE_NUMBER_3 = 'Last 3 digits' +IMAGE_NUMBER_4 = 'Last 4 digits' + + +# Case +ORIGINAL_CASE = "Original Case" +UPPERCASE = "UPPERCASE" +LOWERCASE = "lowercase" + +# Sequence number +SEQUENCE_NUMBER_1 = "One digit" +SEQUENCE_NUMBER_2 = "Two digits" +SEQUENCE_NUMBER_3 = "Three digits" +SEQUENCE_NUMBER_4 = "Four digits" +SEQUENCE_NUMBER_5 = "Five digits" +SEQUENCE_NUMBER_6 = "Six digits" + + +# Now, define dictionaries and lists of valid combinations of preferences. + +# Level 2 + +# Date + +SUBSECONDS = 'Subseconds' + +# ****** note if changing LIST_DATE_TIME_L2, update the default subfolder preference below :D ***** +LIST_DATE_TIME_L2 = ['YYYYMMDD', 'YYYY-MM-DD','YYMMDD', 'YY-MM-DD', + 'MMDDYYYY', 'MMDDYY', 'MMDD', + 'DDMMYYYY', 'DDMMYY', 'YYYY', 'YY', + 'MM', 'DD', + 'HHMMSS', 'HHMM'] + +LIST_IMAGE_DATE_TIME_L2 = LIST_DATE_TIME_L2 + [SUBSECONDS] + +DEFAULT_SUBFOLDER_PREFS = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[9], '/', '', '', DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]] + +class i18TranslateMeThanks: + """ this class is never used in actual running code + It's purpose is to have these values inserted into the program's i18n template file + + """ + def __init__(self): + _('Date time') + _('Text') + _('Filename') + _('Metadata') + _('Sequences') + _('Image date') + _('Today') + _('Yesterday') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Name + extension') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Name') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Extension') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Image number') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Aperture') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('ISO') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Exposure time') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Focal length') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Camera make') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Camera model') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Short camera model') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Hyphenated short camera model') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Serial number') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Shutter count') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata + _('Owner name') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers + _('Downloads today') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers + _('Session number') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers + _('Subfolder number') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers + _('Stored number') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters + _('Sequence letter') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('All digits') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Last digit') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Last 2 digits') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Last 3 digits') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename + _('Last 4 digits') + # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization + _("Original Case") + # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization + _("UPPERCASE") + # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization + _("lowercase") + _("One digit") + _("Two digits") + _("Three digits") + _("Four digits") + _("Five digits") + _("Six digits") + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('Subseconds') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('YYYYMMDD') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('YYYY-MM-DD') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('YYMMDD') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('YY-MM-DD') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('MMDDYYYY') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('MMDDYY') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('MMDD') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('DDMMYYYY') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('DDMMYY') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('YYYY') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('YY') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('MM') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('DD') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('HHMMSS') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('HHMM') + + +# Convenience values for python datetime conversion using values in +# LIST_DATE_TIME_L2. Obviously the two must remain synchronized. + +DATE_TIME_CONVERT = ['%Y%m%d', '%Y-%m-%d','%y%m%d', '%y-%m-%d', + '%m%d%Y', '%m%d%y', '%m%d', + '%d%m%Y', '%d%m%y', '%Y', '%y', + '%m', '%d', + '%H%M%S', '%H%M'] + + +LIST_IMAGE_NUMBER_L2 = [IMAGE_NUMBER_ALL, IMAGE_NUMBER_1, IMAGE_NUMBER_2, + IMAGE_NUMBER_3, IMAGE_NUMBER_4] + + +LIST_CASE_L2 = [ORIGINAL_CASE, UPPERCASE, LOWERCASE] + +LIST_SEQUENCE_LETTER_L2 = [ + UPPERCASE, + LOWERCASE + ] + + + +LIST_SEQUENCE_NUMBERS_L2 = [ + SEQUENCE_NUMBER_1, + SEQUENCE_NUMBER_2, + SEQUENCE_NUMBER_3, + SEQUENCE_NUMBER_4, + SEQUENCE_NUMBER_5, + SEQUENCE_NUMBER_6, + ] + + + +LIST_SHUTTER_COUNT_L2 = [ + SEQUENCE_NUMBER_3, + SEQUENCE_NUMBER_4, + SEQUENCE_NUMBER_5, + SEQUENCE_NUMBER_6, + ] + +# Level 1 +LIST_DATE_TIME_L1 = [IMAGE_DATE, TODAY, YESTERDAY] + +DICT_DATE_TIME_L1 = { + IMAGE_DATE: LIST_IMAGE_DATE_TIME_L2, + TODAY: LIST_DATE_TIME_L2, + YESTERDAY: LIST_DATE_TIME_L2, + ORDER_KEY: LIST_DATE_TIME_L1 + } + + +LIST_FILENAME_L1 = [NAME_EXTENSION, NAME, EXTENSION, IMAGE_NUMBER] + +DICT_FILENAME_L1 = { + NAME_EXTENSION: LIST_CASE_L2, + NAME: LIST_CASE_L2, + EXTENSION: LIST_CASE_L2, + IMAGE_NUMBER: LIST_IMAGE_NUMBER_L2, + ORDER_KEY: LIST_FILENAME_L1 + } + + + +LIST_SUBFOLDER_FILENAME_L1 = [EXTENSION] + +DICT_SUBFOLDER_FILENAME_L1 = { + EXTENSION: LIST_CASE_L2, + ORDER_KEY: LIST_SUBFOLDER_FILENAME_L1 +} + +LIST_METADATA_L1 = [APERTURE, ISO, EXPOSURE_TIME, FOCAL_LENGTH, + CAMERA_MAKE, CAMERA_MODEL, + SHORT_CAMERA_MODEL, + SHORT_CAMERA_MODEL_HYPHEN, + SERIAL_NUMBER, + SHUTTER_COUNT, + OWNER_NAME] + +DICT_METADATA_L1 = { + APERTURE: None, + ISO: None, + EXPOSURE_TIME: None, + FOCAL_LENGTH: None, + CAMERA_MAKE: LIST_CASE_L2, + CAMERA_MODEL: LIST_CASE_L2, + SHORT_CAMERA_MODEL: LIST_CASE_L2, + SHORT_CAMERA_MODEL_HYPHEN: LIST_CASE_L2, + SERIAL_NUMBER: None, + SHUTTER_COUNT: LIST_SHUTTER_COUNT_L2, + OWNER_NAME: LIST_CASE_L2, + ORDER_KEY: LIST_METADATA_L1 + } + + +LIST_SEQUENCE_L1 = [ + DOWNLOAD_SEQ_NUMBER, + STORED_SEQ_NUMBER, + SESSION_SEQ_NUMBER, + SEQUENCE_LETTER + ] + +DICT_SEQUENCE_L1 = { + DOWNLOAD_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2, + STORED_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2, + SESSION_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2, + SEQUENCE_LETTER: LIST_SEQUENCE_LETTER_L2, + ORDER_KEY: LIST_SEQUENCE_L1 + } + + +# Level 0 + + +LIST_IMAGE_RENAME_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, + SEQUENCES] + + +DICT_IMAGE_RENAME_L0 = { + DATE_TIME: DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_FILENAME_L1, + METADATA: DICT_METADATA_L1, + SEQUENCES: DICT_SEQUENCE_L1, + ORDER_KEY: LIST_IMAGE_RENAME_L0 + } + +LIST_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, SEPARATOR] + +DICT_SUBFOLDER_L0 = { + DATE_TIME: DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_SUBFOLDER_FILENAME_L1, + METADATA: DICT_METADATA_L1, + SEPARATOR: None, + ORDER_KEY: LIST_SUBFOLDER_L0 + } + +# preference elements that require metadata +# note there is no need to specify lower level elements if a higher level +# element is necessary for them to be present to begin with +METADATA_ELEMENTS = [METADATA, IMAGE_DATE] + +# preference elements that are sequence numbers or letters +SEQUENCE_ELEMENTS = [ + DOWNLOAD_SEQ_NUMBER, + SESSION_SEQ_NUMBER, + SUBFOLDER_SEQ_NUMBER, + STORED_SEQ_NUMBER, + SEQUENCE_LETTER] + +# preference elements that do not require metadata and are not fixed +# as above, there is no need to specify lower level elements if a higher level +# element is necessary for them to be present to begin with +DYNAMIC_NON_METADATA_ELEMENTS = [ + TODAY, YESTERDAY, + FILENAME] + SEQUENCE_ELEMENTS + + + +#the following is what the preferences looked in older versions of the program +#they are here for reference, and for checking the validity of preferences + +USER_INPUT = 'User' + +DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7 = 'Downloads today' +SESSION_SEQ_NUMBER_V_0_0_8_B7 = 'Session sequence number' +SUBFOLDER_SEQ_NUMBER_V_0_0_8_B7 = 'Subfolder sequence number' +STORED_SEQ_NUMBER_V_0_0_8_B7 = 'Stored sequence number' +SEQUENCE_LETTER_V_0_0_8_B7 = 'Sequence letter' + +LIST_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 = [ + SEQUENCE_NUMBER_1, + SEQUENCE_NUMBER_2, + SEQUENCE_NUMBER_3, + SEQUENCE_NUMBER_4, + SEQUENCE_NUMBER_5, + SEQUENCE_NUMBER_6, + ] + +DICT_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 = { + SEQUENCE_NUMBER_1: None, + SEQUENCE_NUMBER_2: None, + SEQUENCE_NUMBER_3: None, + SEQUENCE_NUMBER_4: None, + SEQUENCE_NUMBER_5: None, + SEQUENCE_NUMBER_6: None, + ORDER_KEY: LIST_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 + } + +LIST_SEQUENCE_L1_V_0_0_8_B7 = [USER_INPUT] + +DICT_SEQUENCE_L1_V_0_0_8_B7 = { + USER_INPUT: DICT_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7, + ORDER_KEY: LIST_SEQUENCE_L1_V_0_0_8_B7 + } + +LIST_SEQUENCE_LETTER_L1_L1_V_0_0_8_B7 = [ + UPPERCASE, + LOWERCASE + ] + +DICT_SEQUENCE_LETTER_L1_V_0_0_8_B7 = { + UPPERCASE: None, + LOWERCASE: None, + ORDER_KEY: LIST_SEQUENCE_LETTER_L1_L1_V_0_0_8_B7 + } + +LIST_IMAGE_RENAME_L0_V_0_0_8_B7 = [DATE_TIME, TEXT, FILENAME, METADATA, + DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7, + SESSION_SEQ_NUMBER_V_0_0_8_B7, + SEQUENCE_LETTER_V_0_0_8_B7] + +DICT_IMAGE_RENAME_L0_V_0_0_8_B7 = { + DATE_TIME: DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_FILENAME_L1, + METADATA: DICT_METADATA_L1, + DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7: None, + SESSION_SEQ_NUMBER_V_0_0_8_B7: None, + SEQUENCE_LETTER_V_0_0_8_B7: DICT_SEQUENCE_LETTER_L1_V_0_0_8_B7, + ORDER_KEY: LIST_IMAGE_RENAME_L0_V_0_0_8_B7 + } + +PREVIOUS_IMAGE_RENAME= { + '0.0.8~b7': DICT_IMAGE_RENAME_L0_V_0_0_8_B7, + } + + +# Functions to work with above data + +def _getPrevPrefs(oldDefs, currentDefs, previousVersion): + k = oldDefs.keys() + # if there were other defns, we'd need to figure out which one + # but currently, there are no others + # there will be in future, and this code wil be updated then + version_change = pythonifyVersion(k[0]) + if pythonifyVersion(previousVersion) <= version_change: + return oldDefs[k[0]] + else: + return currentDefs + +def _upgradePreferencesToCurrent(prefs, previousVersion): + """ checks to see if preferences should be upgraded + + returns True if they were upgraded, and the new prefs + + VERY IMPORTANT: the new prefs will be a new list, not an inplace + modification of the existing preferences! Otherwise, the check on + assignment in the prefs.py __setattr__ will not work as expected!! + """ + upgraded = False + # code to upgrade from <= 0.0.8~b7 to >= 0.0.8~b8 + p = [] + for i in range(0, len(prefs), 3): + if prefs[i] in [SEQUENCE_LETTER_V_0_0_8_B7, SESSION_SEQ_NUMBER_V_0_0_8_B7]: + upgraded = True + p.append(SEQUENCES) + if prefs[i] == SEQUENCE_LETTER_V_0_0_8_B7: + p.append(SEQUENCE_LETTER) + p.append(prefs[i+1]) + else: + p.append(SESSION_SEQ_NUMBER) + p.append(prefs[i+2]) + else: + p += prefs[i:i+3] + + assert(len(prefs)==len(p)) + return (upgraded, p) + + +def upgradePreferencesToCurrent(imageRenamePrefs, subfolderPrefs, previousVersion): + """Upgrades user preferences to current version + + returns True if the preferences were upgraded""" + + # only check image rename, for now.... + upgraded, imageRenamePrefs = _upgradePreferencesToCurrent(imageRenamePrefs, previousVersion) + return (upgraded, imageRenamePrefs , subfolderPrefs) + +def checkPreferencesForValidity(imageRenamePrefs, subfolderPrefs, version=config.version): + """Returns true if the passed in preferences are valid""" + + if version == config.version: + try: + checkPreferenceValid(DICT_SUBFOLDER_L0, subfolderPrefs) + checkPreferenceValid(DICT_IMAGE_RENAME_L0, imageRenamePrefs) + except: + return False + return True + else: + defn = _getPrevPrefs(PREVIOUS_IMAGE_RENAME, DICT_IMAGE_RENAME_L0, version) + try: + checkPreferenceValid(defn, imageRenamePrefs) + checkPreferenceValid(DICT_SUBFOLDER_L0, subfolderPrefs) + except: + return False + return True + +def checkPreferenceValid(prefDefinition, prefs, modulo=3): + """ + Checks to see if prefs are valid according to definition. + + prefs is a list of preferences. + prefDefinition is a Dict specifying what is valid. + modulo is how many list elements are equivalent to one line of preferences. + + Returns True if prefs match with prefDefinition, + else raises appropriate error. + """ + + if (len(prefs) % modulo <> 0) or not prefs: + raise PrefLengthError(prefs) + else: + for i in range(0, len(prefs), modulo): + _checkPreferenceValid(prefDefinition, prefs[i:i+modulo]) + + return True + +def _checkPreferenceValid(prefDefinition, prefs): + + key = prefs[0] + value = prefs[1] + + + if prefDefinition.has_key(key): + + nextPrefDefinition = prefDefinition[key] + + if value == None: + # value should never be None, at any time + raise PrefValueInvalidError((None, nextPrefDefinition)) + + if nextPrefDefinition and not value: + raise PrefValueInvalidError((value, nextPrefDefinition)) + + if type(nextPrefDefinition) == type({}): + return _checkPreferenceValid(nextPrefDefinition, prefs[1:]) + else: + if type(nextPrefDefinition) == type([]): + result = value in nextPrefDefinition + if not result: + raise PrefValueInvalidError((value, nextPrefDefinition)) + return True + elif not nextPrefDefinition: + return True + else: + result = nextPrefDefinition == value + if not result: + raise PrefKeyValue((value, nextPrefDefinition)) + return True + else: + raise PrefKeyError((key, prefDefinition[ORDER_KEY])) + +def filterSubfolderPreferences(prefList): + """ + Filters out extraneous preference choices + """ + prefs_changed = False + continueCheck = True + while continueCheck and prefList: + continueCheck = False + if prefList[0] == SEPARATOR: + # Subfolder preferences should not start with a / + prefList = prefList[3:] + prefs_changed = True + continueCheck = True + elif prefList[-3] == SEPARATOR: + # Subfolder preferences should not end with a / + prefList = prefList[:-3] + continueCheck = True + prefs_changed = True + else: + for i in range(0, len(prefList) - 3, 3): + if prefList[i] == SEPARATOR and prefList[i+3] == SEPARATOR: + # Subfolder preferences should not contain two /s side by side + continueCheck = True + prefs_changed = True + # note we are messing with the contents of the pref list, + # must exit loop and try again + prefList = prefList[:i] + prefList[i+3:] + break + + return (prefs_changed, prefList) + + +class PrefError(Exception): + """ base class """ + def unpackList(self, l): + s = '' + for i in l: + if i <> ORDER_KEY: + s += "'" + i + "', " + return s[:-2] + + def __str__(self): + return self.msg + +class PrefKeyError(PrefError): + def __init__(self, error): + value = error[0] + expectedValues = self.unpackList(error[1]) + self.msg = _("Preference key '%(key)s' is invalid.\nExpected one of %(value)s") % { + 'key': value, 'value': expectedValues} + + +class PrefValueInvalidError(PrefKeyError): + def __init__(self, error): + value = error[0] + self.msg = _("Preference value '%(value)s' is invalid") % {'value': value} + +class PrefLengthError(PrefError): + def __init__(self, error): + self.msg = _("These preferences are not well formed:") % self.unpackList(error) + "\n %s" + +class PrefValueKeyComboError(PrefError): + def __init__(self, error): + self.msg = error + + +def convertDateForStrftime(dateTimeUserChoice): + try: + return DATE_TIME_CONVERT[LIST_DATE_TIME_L2.index(dateTimeUserChoice)] + except: + raise PrefValueInvalidError(dateTimeUserChoice) + + +class Comboi18n(gtk.ComboBox): + """ very simple i18n version of the venerable combo box + with one column displayed to the user. + + This combo box has two columns: + 1. the first contains the actual value and is invisible + 2. the second contains the translation of the first column, and this is what + the users sees + """ + def __init__(self): + liststore = gtk.ListStore(str, str) + gtk.ComboBox.__init__(self, liststore) + cell = gtk.CellRendererText() + self.pack_start(cell, True) + self.add_attribute(cell, 'text', 1) + + def append_text(self, text): + model = self.get_model() + model.append((text, _(text))) + + def get_active_text(self): + model = self.get_model() + active = self.get_active() + if active < 0: + return None + return model[active][0] + +class ImageRenamePreferences: + def __init__(self, prefList, parent, fileSequenceLock=None, sequences=None): + """ + Exception raised if preferences are invalid. + + This should be caught by calling class.""" + + self.parent = parent + self.prefList = prefList + + # use variables for determining sequence numbers + # there are two possibilities: + # 1. this code is being called while being run from within a copy photos process + # 2. it's being called from within the preferences dialog window + + self.fileSequenceLock = fileSequenceLock + self.sequences = sequences + + # derived classes will have their own definitions, do not overwrite + if not hasattr(self, "prefsDefnL0"): + self.prefsDefnL0 = DICT_IMAGE_RENAME_L0 + self.defaultPrefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE] + self.defaultRow = self.defaultPrefs + self.stripForwardSlash = True + + + + def checkPrefsForValidity(self): + """ + Checks image preferences validity + """ + + return checkPreferenceValid(self.prefsDefnL0, self.prefList) + + def formatPreferencesForPrettyPrint(self): + """ returns a string useful for printing the preferences""" + + v = '' + + for i in range(0, len(self.prefList), 3): + s = "%s: " % self.prefList[i] + if self.prefList[i+1]: + s = "%s%s" % (s, self.prefList[i+1]) + if self.prefList[i+2]: + s = "%s (%s)" % (s, self.prefList[i+2]) + + v += s + "\n" + return v + + + def _getDateComponent(self): + """ + Returns portion of new image / subfolder name based on date time + """ + + problem = None + if self.L1 == IMAGE_DATE: + if self.L2 == SUBSECONDS: + d = self.photo.subSeconds() + problem = _("Subsecond metadata not present in image") + else: + d = self.photo.dateTime(missing=None) + problem = _("%s metadata is not present in image") % self.L1.lower() + elif self.L1 == TODAY: + d = datetime.datetime.now() + elif self.L1 == YESTERDAY: + delta = datetime.timedelta(days = 1) + d = datetime.datetime.now() - delta + else: + raise("Date options invalid") + + if d: + if self.L2 <> SUBSECONDS: + try: + return (d.strftime(convertDateForStrftime(self.L2)), None) + except: + v = '' + problem = _('Error in date time component. Value %s appears invalid') % d + return (v, problem) + else: + return (d, None) + else: + return ('', problem) + + def _getFilenameComponent(self): + """ + Returns portion of new image / subfolder name based on the file name + """ + + name, extension = os.path.splitext(self.existingFilename) + problem = None + + if self.L1 == NAME_EXTENSION: + filename = self.existingFilename + elif self.L1 == NAME: + filename = name + elif self.L1 == EXTENSION: + if extension: + if not self.stripInitialPeriodFromExtension: + # keep the period / dot of the extension, so the user does not + # need to manually specify it + filename = extension + else: + # having the period when this is used as a part of a subfolder name + # is a bad idea! + filename = extension[1:] + else: + filename = "" + problem = _("extension was specified but image name has no extension") + elif self.L1 == IMAGE_NUMBER: + n = re.search("(?P<image_number>[0-9]+$)", name) + if not n: + problem = _("image number was specified but image filename has no number") + else: + image_number = n.group("image_number") + + if self.L2 == IMAGE_NUMBER_ALL: + filename = image_number + elif self.L2 == IMAGE_NUMBER_1: + filename = image_number[-1] + elif self.L2 == IMAGE_NUMBER_2: + filename = image_number[-2:] + elif self.L2 == IMAGE_NUMBER_3: + filename = image_number[-3:] + elif self.L2 == IMAGE_NUMBER_4: + filename = image_number[-4:] + else: + raise TypeError("Incorrect filename option") + + if self.L2 == UPPERCASE: + filename = filename.upper() + elif self.L2 == LOWERCASE: + filename = filename.lower() + + return (filename, problem) + + def _getMetadataComponent(self): + """ + Returns portion of new image / subfolder name based on the metadata + + Note: date time metadata found in _getDateComponent() + """ + + problem = None + if self.L1 == APERTURE: + v = self.photo.aperture() + elif self.L1 == ISO: + v = self.photo.iso() + elif self.L1 == EXPOSURE_TIME: + v = self.photo.exposureTime(alternativeFormat=True) + elif self.L1 == FOCAL_LENGTH: + v = self.photo.focalLength() + elif self.L1 == CAMERA_MAKE: + v = self.photo.cameraMake() + elif self.L1 == CAMERA_MODEL: + v = self.photo.cameraModel() + elif self.L1 == SHORT_CAMERA_MODEL: + v = self.photo.shortCameraModel() + elif self.L1 == SHORT_CAMERA_MODEL_HYPHEN: + v = self.photo.shortCameraModel(includeCharacters = "\-") + elif self.L1 == SERIAL_NUMBER: + v = self.photo.cameraSerial() + elif self.L1 == SHUTTER_COUNT: + v = self.photo.shutterCount() + if v: + v = int(v) + padding = LIST_SHUTTER_COUNT_L2.index(self.L2) + 3 + formatter = '%0' + str(padding) + "i" + v = formatter % v + + elif self.L1 == OWNER_NAME: + v = self.photo.ownerName() + else: + raise TypeError("Invalid metadata option specified") + if self.L1 in [CAMERA_MAKE, CAMERA_MODEL, SHORT_CAMERA_MODEL, + SHORT_CAMERA_MODEL_HYPHEN, OWNER_NAME]: + if self.L2 == UPPERCASE: + v = v.upper() + elif self.L2 == LOWERCASE: + v = v.lower() + if not v: + if self.L1 <> ISO: + md = self.L1.lower() + else: + md = ISO + problem = _("%s metadata is not present in image") % md + return (v, problem) + + + def _formatSequenceNo(self, value, amountToPad): + padding = LIST_SEQUENCE_NUMBERS_L2.index(amountToPad) + 1 + formatter = '%0' + str(padding) + "i" + return formatter % value + + + def _calculateLetterSequence(self, sequence): + + def _letters(x): + """ + Adapted from algorithm at http://en.wikipedia.org/wiki/Hexavigesimal + """ + v = '' + while x > 25: + r = x % 26 + x= x / 26 - 1 + v = string.lowercase[r] + v + v = string.lowercase[x] + v + + return v + + + v = _letters(sequence) + if self.L2 == UPPERCASE: + v = v.upper() + + return v + + def _getSubfolderSequenceNo(self): + """ + Add a sequence number to the filename + + * Sequence numbering is per subfolder + * Assume the user might actually have a (perhaps odd) reason to have more + than one subfolder sequence number in the same file name + """ + + problem = None + self.subfolderSeqNoInstanceInFilename += 1 + + if self.downloadSubfolder: + subfolder = self.downloadSubfolder + str(self.subfolderSeqNoInstanceInFilename) + else: + subfolder = "__subfolder__" + str(self.subfolderSeqNoInstanceInFilename) + + if self.fileSequenceLock: + with self.fileSequenceLock: + v = self.sequenceNos.calculate(subfolder) + v = self.formatSequenceNo(v, self.L1) + else: + v = self.sequenceNos.calculate(subfolder) + v = self.formatSequenceNo(v, self.L1) + + return (v, problem) + + def _getSessionSequenceNo(self): + problem = None + v = self._formatSequenceNo(self.sequences.getSessionSequenceNoUsingCounter(self.sequenceCounter), self.L2) + return (v, problem) + + def _getDownloadsTodaySequenceNo(self): + problem = None + + v = self._formatSequenceNo(self.sequences.getDownloadsTodayUsingCounter(self.sequenceCounter), self.L2) + + return (v, problem) + + def _getStoredSequenceNo(self): + problem = None + v = self._formatSequenceNo(self.sequences.getStoredSequenceNoUsingCounter(self.sequenceCounter), self.L2) + + return (v, problem) + + def _getSequenceLetter(self): + + problem = None + v = self._calculateLetterSequence(self.sequences.getSequenceLetterUsingCounter(self.sequenceCounter)) + return (v, problem) + + def _getSequencesComponent(self): + problem = None + if self.L1 == DOWNLOAD_SEQ_NUMBER: + return self._getDownloadsTodaySequenceNo() + elif self.L1 == SESSION_SEQ_NUMBER: + return self._getSessionSequenceNo() + elif self.L1 == SUBFOLDER_SEQ_NUMBER: + return self._getSubfolderSequenceNo() + elif self.L1 == STORED_SEQ_NUMBER: + return self._getStoredSequenceNo() + elif self.L1 == SEQUENCE_LETTER: + return self._getSequenceLetter() + + def _getComponent(self): + try: + if self.L0 == DATE_TIME: + return self._getDateComponent() + elif self.L0 == TEXT: + return (self.L1, None) + elif self.L0 == FILENAME: + return self._getFilenameComponent() + elif self.L0 == METADATA: + return self._getMetadataComponent() + elif self.L0 == SEQUENCES: + return self._getSequencesComponent() + elif self.L0 == SEPARATOR: + return (os.sep, None) + except: + v = "" + problem = _("error generating name with component %s") % self.L2 + return (v, problem) + + def _getValuesFromList(self): + for i in range(0, len(self.prefList), 3): + yield (self.prefList[i], self.prefList[i+1], self.prefList[i+2]) + + + def _generateName(self, photo, existingFilename, stripCharacters, subfolder, stripInitialPeriodFromExtension, sequence): + self.photo = photo + self.existingFilename = existingFilename + self.stripInitialPeriodFromExtension = stripInitialPeriodFromExtension + + name = '' + problem = '' + + #the subfolder in which the image will be downloaded to + self.downloadSubfolder = subfolder + + self.sequenceCounter = sequence + + for self.L0, self.L1, self.L2 in self._getValuesFromList(): + v, p = self._getComponent() + if v: + name += v + if p: + problem += p + "; " + + if problem: + # remove final semicolon and space + problem = problem[:-2] + '.' + + if stripCharacters: + for c in r'\:*?"<>|': + name = name.replace(c, '') + + if self.stripForwardSlash: + name = name.replace('/', '') + + return (name, problem) + + def generateNameUsingPreferences(self, photo, existingFilename=None, + stripCharacters = False, subfolder=None, + stripInitialPeriodFromExtension=False, + sequencesPreliminary = True): + """ + Generate a filename for the photo in string format based on user prefs. + + Returns a tuple of two strings: + - the name + - any problems generating the name. If blank, there were no problems + """ + + if self.sequences: + if sequencesPreliminary: + sequence = self.sequences.getPrelimSequence() + else: + sequence = self.sequences.getFinalSequence() + else: + sequence = 0 + + return self._generateName(photo, existingFilename, stripCharacters, subfolder, + stripInitialPeriodFromExtension, sequence) + + def generateNameSequencePossibilities(self, photo, existingFilename, + stripCharacters=False, subfolder=None, + stripInitialPeriodFromExtension=False): + + """ Generates the possible image names using the sequence numbers / letter possibilities""" + + for sequence in self.sequences.getSequencePossibilities(): + yield self._generateName(photo, existingFilename, stripCharacters , subfolder, + stripInitialPeriodFromExtension, sequence) + + def filterPreferences(self): + """ + Filters out extraneous preference choices + Expected to be implemented in derived classes when needed + """ + pass + + def needImageMetaDataToCreateUniqueName(self): + """ + Returns True if an image's metadata is essential to properly generate a unique image name + + Image names should be unique. Some images may not have metadata. If + only non-dynamic components make up the rest of an image name + (e.g. text specified by the user), then relying on metadata will likely + produce duplicate names. + + File extensions are not considered dynamic. + + This is NOT a general test to see if unique filenames can be generated. It is a test + to see if an image's metadata is needed. + """ + hasMD = hasDynamic = False + + for e in METADATA_ELEMENTS: + if e in self.prefList: + hasMD = True + break + + if hasMD: + for e in DYNAMIC_NON_METADATA_ELEMENTS: + if e in self.prefList: + if e == FILENAME and (NAME_EXTENSION in self.prefList or + NAME in self.prefList or + IMAGE_NUMBER in self.prefList): + hasDynamic = True + break + + if hasMD and not hasDynamic: + return True + else: + return False + + def usesSequenceElements(self): + """ Returns true if any sequence numbers or letters are used to generate the filename """ + + for e in SEQUENCE_ELEMENTS: + if e in self.prefList: + return True + + return False + + def usesTheSequenceElement(self, e): + """ Returns true if a stored sequence number is used to generate the filename """ + return e in self.prefList + + + def _createCombo(self, choices): + combobox = Comboi18n() + for text in choices: + combobox.append_text(text) + return combobox + + def getDefaultRow(self): + """ + returns a list of default widgets + """ + return self.getWidgetsBasedOnUserSelection(self.defaultRow) + + def _getPreferenceWidgets(self, prefDefinition, prefs, widgets): + key = prefs[0] + value = prefs[1] + + # supply a default value if the user has not yet chosen a value! + if not key: + key = prefDefinition[ORDER_KEY][0] + + if not key in prefDefinition: + raise PrefKeyError((key, prefDefinition.keys())) + + + list0 = prefDefinition[ORDER_KEY] + + # the first widget will always be a combo box + widget0 = self._createCombo(list0) + widget0.set_active(list0.index(key)) + + widgets.append(widget0) + + if key == TEXT: + widget1 = gtk.Entry() + widget1.set_text(value) + + widgets.append(widget1) + widgets.append(None) + return + elif key == SEPARATOR: + widgets.append(None) + widgets.append(None) + return + else: + nextPrefDefinition = prefDefinition[key] + if type(nextPrefDefinition) == type({}): + return self._getPreferenceWidgets(nextPrefDefinition, + prefs[1:], + widgets) + else: + if type(nextPrefDefinition) == type([]): + widget1 = self._createCombo(nextPrefDefinition) + if not value: + value = nextPrefDefinition[0] + try: + widget1.set_active(nextPrefDefinition.index(value)) + except: + raise PrefValueInvalidError((value, nextPrefDefinition)) + + widgets.append(widget1) + else: + widgets.append(None) + + def getWidgetsBasedOnPreferences(self): + """ + Yields a list of widgets and their callbacks based on the users preferences. + + This list is equivalent to one row of preferences when presented to the + user in the Plus Minus Table. + """ + + for L0, L1, L2 in self._getValuesFromList(): + prefs = [L0, L1, L2] + widgets = [] + self._getPreferenceWidgets(self.prefsDefnL0, prefs, widgets) + yield widgets + + + def getWidgetsBasedOnUserSelection(self, selection): + """ + Returns a list of widgets and their callbacks based on what the user has selected. + + Selection is the values the user has chosen thus far in comboboxes. + It determines the contents of the widgets returned. + It should be a list of three values, with None for values not chosen. + For values which are None, the first value in the preferences + definition is chosen. + + """ + widgets = [] + + self._getPreferenceWidgets(self.prefsDefnL0, selection, widgets) + return widgets + +class SubfolderPreferences(ImageRenamePreferences): + def __init__(self, prefList, parent): + self.prefsDefnL0 = DICT_SUBFOLDER_L0 + self.defaultPrefs = DEFAULT_SUBFOLDER_PREFS + self.defaultRow = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]] + self.stripForwardSlash = False + ImageRenamePreferences.__init__(self, prefList, parent) + + def generateNameUsingPreferences(self, photo, existingFilename=None, + stripCharacters = False): + """ + Generate a filename for the photo in string format based on user prefs. + + Returns a tuple of two strings: + - the name + - any problems generating the name. If blank, there were no problems + """ + + subfolders, problem = ImageRenamePreferences.generateNameUsingPreferences( + self, photo, + existingFilename, stripCharacters, stripInitialPeriodFromExtension=True) + # subfolder value must never start with a separator, or else any + # os.path.join function call will fail to join a subfolder to its + # parent folder + if subfolders: + if subfolders[0] == os.sep: + subfolders = subfolders[1:] + + return (subfolders, problem) + + def filterPreferences(self): + filtered, prefList = filterSubfolderPreferences(self.prefList) + if filtered: + self.prefList = prefList + + def needMetaDataToCreateUniqueName(self): + """ + Returns True if metadata is essential to properly generate subfolders + + This will be the case if the only components are metadata and separators + """ + + for e in self.prefList: + if (not e) and ((e not in METADATA_ELEMENTS) or (e <> SEPARATOR)): + return True + + return False + + + + + def checkPrefsForValidity(self): + """ + Checks subfolder preferences validity above and beyond image name checks. + + See parent method for full description. + + Subfolders have additional requirments to that of image names. + """ + v = ImageRenamePreferences.checkPrefsForValidity(self) + if v: + # peform additional checks: + # 1. do not start with a separator + # 2. do not end with a separator + # 3. do not have two separators in a row + # these three rules will ensure something else other than a + # separator is specified + L1s = [] + for i in range(0, len(self.prefList), 3): + L1s.append(self.prefList[i]) + + if L1s[0] == SEPARATOR: + raise PrefValueKeyComboError(_("Subfolder preferences should not start with a %s") % os.sep) + elif L1s[-1] == SEPARATOR: + raise PrefValueKeyComboError(_("Subfolder preferences should not end with a %s") % os.sep) + else: + for i in range(len(L1s) - 1): + if L1s[i] == SEPARATOR and L1s[i+1] == SEPARATOR: + raise PrefValueKeyComboError(_("Subfolder preferences should not contain two %s one after the other") % os.sep) + return v + + +class Sequences: + """ Holds sequence numbers and letters used in generating filenames""" + def __init__(self, downloadsToday, storedSequenceNo): + + + self.subfolderSequenceNo = {} + self.sessionSequenceNo = 1 + self.sequenceLetter = 0 + + self.setUseOfSequenceElements(False, False) + + self.assignedSequenceCounter = 1 + self.reset(downloadsToday, storedSequenceNo) + + def setUseOfSequenceElements(self, usesSessionSequenceNo, usesSequenceLetter): + self.usesSessionSequenceNo = usesSessionSequenceNo + self.usesSequenceLetter = usesSequenceLetter + + def reset(self, downloadsToday, storedSequenceNo): + self.downloadsToday = downloadsToday + self.downloadsTodayOffset = 0 + self.storedSequenceNo = storedSequenceNo + if self.usesSessionSequenceNo: + self.sessionSequenceNo = self.sessionSequenceNo + self.assignedSequenceCounter - 1 + if self.usesSequenceLetter: + self.sequenceLetter = self.sequenceLetter + self.assignedSequenceCounter - 1 + self.doNotAddToPool = False + self.pool = [] + self.poolSequenceCounter = 0 + self.assignedSequenceCounter = 1 + + def getPrelimSequence(self): + if self.doNotAddToPool: + self.doNotAddToPool = False + else: + # increment pool sequence number + self.poolSequenceCounter += 1 + self.pool.append(self.poolSequenceCounter) + + return self.poolSequenceCounter + + def getFinalSequence(self): + # get oldest queue value + # remove from queue or flag it should be removed + + return self.assignedSequenceCounter + + def getSequencePossibilities(self): + for i in self.pool: + yield i + + def getSessionSequenceNo(self): + return self.sessionSequenceNo + self.assignedSequenceCounter - 1 + + def getSessionSequenceNoUsingCounter(self, counter): + return self.sessionSequenceNo + counter - 1 + + def setSessionSequenceNo(self, value): + self.sessionSequenceNo = value + + def setStoredSequenceNo(self, value): + self.storedSequenceNo = value + + def getDownloadsTodayUsingCounter(self, counter): + return self.downloadsToday + counter - self.downloadsTodayOffset + + def setDownloadsToday(self, value): + self.downloadsToday = value + self.downloadsTodayOffset = self.assignedSequenceCounter - 1 + + def getStoredSequenceNoUsingCounter(self, counter): + return self.storedSequenceNo + counter + + def getSequenceLetterUsingCounter(self, counter): + return self.sequenceLetter + counter - 1 + + def imageCopyFailed(self): + self.doNotAddToPool = True + + def imageCopySucceeded(self): + self.increment() + + def increment(self, subfolder=None): + assert(self.assignedSequenceCounter == self.pool[0]) + self.assignedSequenceCounter += 1 + self.pool = self.pool[1:] + + + + +if __name__ == '__main__': + import sys + import os.path + from metadata import MetaData + + if False: + if (len(sys.argv) != 2): + print 'Usage: ' + sys.argv[0] + ' path/to/photo/containing/metadata' + sys.exit(1) + else: + p0 = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE] + p1 = [FILENAME, NAME_EXTENSION, LOWERCASE] + p2 = [METADATA, APERTURE, None] + p3 = [FILENAME, IMAGE_NUMBER, IMAGE_NUMBER_ALL] + p4 = [METADATA, CAMERA_MODEL, ORIGINAL_CASE] + p5 = [TEXT, '-', None] + p6 = [TEXT, 'Job', None] + + p = [p0, p1, p2, p3, p4] + p = [p6 + p5 + p2 + p5 + p3] + + d0 = [DATE_TIME, IMAGE_DATE, 'YYYYMMDD'] + d1 = [DATE_TIME, IMAGE_DATE, 'HHMMSS'] + d2 = [DATE_TIME, IMAGE_DATE, SUBSECONDS] + + d = [d0 + d1 + d2] + + fullpath = sys.argv[1] + path, filename = os.path.split(fullpath) + + m = MetaData(fullpath) + m.readMetadata() + + for pref in p: + i = ImageRenamePreferences(pref, None) + print i.generateNameUsingPreferences(m, filename) + + for pref in d: + i = ImageRenamePreferences(pref, None) + print i.generateNameUsingPreferences(m, filename) + else: + prefs = [SEQUENCES, SESSION_SEQ_NUMBER, SEQUENCE_NUMBER_3] +# prefs = ['Filename2', NAME_EXTENSION, UPPERCASE] + print checkPreferenceValid(DICT_IMAGE_RENAME_L0, prefs) diff --git a/rapid/renamesubfolderprefstest.py b/rapid/renamesubfolderprefstest.py new file mode 100644 index 0000000..a689c5c --- /dev/null +++ b/rapid/renamesubfolderprefstest.py @@ -0,0 +1,190 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +import unittest + +from renamesubfolderprefs import * + +class PreferenceTest (unittest.TestCase): + image_test = ( [TEXT, '', ''], + [DATE_TIME, IMAGE_DATE, 'YYYYMMDD'], + [METADATA, APERTURE, ''], + [FILENAME, NAME_EXTENSION, UPPERCASE], + ) + subfolder_test = ( [TEXT, '', ''], + [DATE_TIME, IMAGE_DATE, 'HHMM'], + [METADATA, SHORT_CAMERA_MODEL_HYPHEN, + LOWERCASE], + [SEPARATOR, '', ''], + [FILENAME, EXTENSION, LOWERCASE] + ) + + trueMetadataTest = ([FILENAME, EXTENSION, LOWERCASE, TEXT, '', '', METADATA, APERTURE, ''], [METADATA, APERTURE, '', TEXT, '', '', FILENAME, EXTENSION, LOWERCASE], ) + + falseMetadataTest = ([FILENAME, EXTENSION, LOWERCASE, METADATA, APERTURE, '', FILENAME, NAME, LOWERCASE], + [FILENAME, NAME, LOWERCASE, FILENAME, EXTENSION, LOWERCASE], + [FILENAME, NAME_EXTENSION, LOWERCASE, FILENAME, EXTENSION, LOWERCASE], + [FILENAME, NAME, LOWERCASE, FILENAME, METADATA, EXPOSURE_TIME, '', IMAGE_NUMBER, IMAGE_NUMBER_ALL, FILENAME, EXTENSION, LOWERCASE], ) + + sequences_test = ([SEQUENCES, SESSION_SEQ_NUMBER, SEQUENCE_NUMBER_3], + [FILENAME, NAME, LOWERCASE, SEQUENCES, DOWNLOAD_SEQ_NUMBER, SEQUENCE_NUMBER_1, + FILENAME, EXTENSION, UPPERCASE], + [METADATA, APERTURE, '', SEQUENCES, STORED_SEQ_NUMBER, SEQUENCE_NUMBER_5, + FILENAME, EXTENSION, UPPERCASE], ) + + def testPrefImageList(self): + for pref in self.image_test: + result = checkPreferenceValid(DICT_IMAGE_RENAME_L0, pref) + self.assertEqual(result, True) + + def testSequencesList(self): + for pref in self.sequences_test: + result = checkPreferenceValid(DICT_IMAGE_RENAME_L0, pref) + self.assertEqual(result, True) + + def testNeedImageMetaDataToCreateUniqueName(self): + for i in self.trueMetadataTest: + p = ImageRenamePreferences(i, None) + result = p.needImageMetaDataToCreateUniqueName() + self.assertEqual(result, True) + + for i in self.falseMetadataTest: + p = ImageRenamePreferences(i, None) + result = p.needImageMetaDataToCreateUniqueName() + self.assertEqual(result, False) + + + + def testLargePrefList(self): + prefList = [] + for pref in self.image_test: + for l in pref: + prefList.append(l) + + result = checkPreferenceValid(DICT_IMAGE_RENAME_L0, prefList) + self.assertEqual(result, True) + + def testPrefSubfolderList(self): + for pref in self.subfolder_test: + result = checkPreferenceValid(DICT_SUBFOLDER_L0, pref) + self.assertEqual(result, True) + + def testDateTimeL2Length(self): + self.assertEqual(len(LIST_DATE_TIME_L2), len(DATE_TIME_CONVERT)) + + def testDateTimeL2Conversion(self): + self.assertEqual(convertDateForStrftime('YY'), '%y') + + + +class BadPreferences(unittest.TestCase): + bad_image_key = ( [TEXT, '', '', + DATE_TIME, IMAGE_DATE, 'YYYYMMDD', + METADATA, APERTURE, '', + FILENAME, NAME_EXTENSION, UPPERCASE, + 'Filename2', NAME_EXTENSION, UPPERCASE], + ) + bad_image_value = ( [DATE_TIME, TODAY, IMAGE_NUMBER_ALL], + [METADATA, CAMERA_MAKE, IMAGE_NUMBER_4], + [DATE_TIME, IMAGE_DATE, None], + [DATE_TIME, IMAGE_DATE, ''], + [DATE_TIME, None, None], + [DATE_TIME, '', ''], + ) + + bad_subfolder_key = ([FILENAME, NAME_EXTENSION, UPPERCASE],) + + bad_subfolder_key2 = ( [TEXT, '', '', + DATE_TIME, IMAGE_DATE, 'HHMM', + METADATA, SHORT_CAMERA_MODEL_HYPHEN, + LOWERCASE, + SEPARATOR, '', '', + 'Filename-bad', EXTENSION, LOWERCASE], + ) + + bad_subfolder_value = ( [FILENAME, None, None], + [FILENAME, '', ''],) + + bad_length = ([], [DATE_TIME, TODAY], [DATE_TIME]) + + bad_dt_conversion = ('HHYY', 'YYSS') + + bad_subfolder_combos = ([SEPARATOR, '', ''], + [FILENAME, EXTENSION, UPPERCASE, + SEPARATOR, '', ''], + [FILENAME, EXTENSION, UPPERCASE, + SEPARATOR, '', '', + SEPARATOR, '', '', + FILENAME, EXTENSION, UPPERCASE + ], + [SEPARATOR, '', '', + SEPARATOR, '', '', + SEPARATOR, '', '', + SEPARATOR, '', '' + ] + ) + + def testBadImageKey(self): + for pref in self.bad_image_key: + self.assertRaises(PrefKeyError, checkPreferenceValid, + DICT_IMAGE_RENAME_L0, + pref) + + def testBadImageValue(self): + for pref in self.bad_image_value: + self.assertRaises(PrefValueInvalidError, checkPreferenceValid, + DICT_IMAGE_RENAME_L0, + pref) + + def testBadSubfolderKey(self): + for pref in self.bad_subfolder_key: + self.assertRaises(PrefKeyError, checkPreferenceValid, + DICT_SUBFOLDER_L0, + pref) + + for pref in self.bad_subfolder_key2: + self.assertRaises(PrefKeyError, checkPreferenceValid, + DICT_SUBFOLDER_L0, + pref) + + + def testBadSubfolderValue(self): + for pref in self.bad_subfolder_value: + self.assertRaises(PrefValueInvalidError, checkPreferenceValid, + DICT_SUBFOLDER_L0, + pref) + + def testBadLength(self): + for pref in self.bad_length: + self.assertRaises(PrefLengthError, checkPreferenceValid, + DICT_IMAGE_RENAME_L0, + pref) + def testBadDTConversion(self): + for pref in self.bad_dt_conversion: + self.assertRaises(PrefValueInvalidError, convertDateForStrftime, + pref) + + def testBadSubfolderCombo(self): + + for pref in self.bad_subfolder_combos: + s = SubfolderPreferences(pref, self) + self.assertRaises(PrefValueKeyComboError, s.checkPrefsForValidity) + +if __name__ == "__main__": + unittest.main() diff --git a/rapid/tableplusminus.py b/rapid/tableplusminus.py new file mode 100644 index 0000000..ab7e7c1 --- /dev/null +++ b/rapid/tableplusminus.py @@ -0,0 +1,284 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com> + +### This program is free software; you can redistribute it and/or modify +### it under the terms of the GNU General Public License as published by +### the Free Software Foundation; either version 2 of the License, or +### (at your option) any later version. + +### This program is distributed in the hope that it will be useful, +### but WITHOUT ANY WARRANTY; without even the implied warranty of +### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +### GNU General Public License for more details. + +### You should have received a copy of the GNU General Public License +### along with this program; if not, write to the Free Software +### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# import gtk.gdk as gdk +import sys +try: + import pygtk + pygtk.require("2.0") +except: + pass +try: + import gtk +except: + sys.exit(1) + +import higdefaults as hd + +class TablePlusMinus(gtk.Table): + """ + A regular gtk table which allows users to add and delete rows to the table. + + Users add and delete rows by using plus and minus buttons. + The buttons (minus first) are in the two rightmost colums. + The user can never delete a table so it has no rows. + """ + + debug = False # if True, then debugging info for the developer is displayed + def __init__(self, rows=1, columns=1, homogeneous=False): + if not self.debug: + gtk.Table.__init__(self, rows, columns + 2, homogeneous) + self.extraCols = 2 # representing minus and plus buttons + else: + gtk.Table.__init__(self, rows, columns + 3, homogeneous) + self.extraCols = 3 # representing minus and plus buttons, and info label + + # no of columns NOT including the + and - buttons + self.pm_noColumns = columns + # how many rows there are in the gtk.Table + self.pm_noRows = rows + # list of widgets in the gtk.Table + self.pm_rows = [] + # dict of callback ids for minus and plus buttons + self.pm_callbacks = {} + + #spacing of controls + for i in range(columns-1): + self.set_col_spacing(i, hd.CONTROL_IN_TABLE_SPACE) + self.set_col_spacing(columns-1, hd.CONTROL_IN_TABLE_SPACE*2) + self.set_col_spacing(columns, hd.CONTROL_IN_TABLE_SPACE) + if self.debug: + self.set_col_spacing(columns+1, hd.CONTROL_IN_TABLE_SPACE) + self.set_row_spacings(hd.CONTROL_IN_TABLE_SPACE) + + def _setMinusButtonSensitivity(self): + button = self.pm_rows[0][self.pm_noColumns] + if len(self.pm_rows) == 1: + button.set_sensitive(False) + else: + button.set_sensitive(True) + + def _createMinusPlusButtons(self, rowPosition): + plus_button = gtk.Button() + plus_button.set_image(gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU)) + self._createCallback(plus_button, rowPosition, 'clicked', self.on_plus_button_clicked) + minus_button = gtk.Button() + minus_button.set_image(gtk.image_new_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU)) + self._createCallback(minus_button, rowPosition, 'clicked', self.on_minus_button_clicked) + + return minus_button, plus_button + + + + def append(self, row): + self.insertAfter(len(self.pm_rows)-1, row) + + + def _getMinusAndPlusButtonsForRow(self, rowPosition): + """ + Return as a tuple minus and plus buttons for the row specified by rowPosition + """ + return (self.pm_rows[rowPosition][self.pm_noColumns], self.pm_rows[rowPosition][self.pm_noColumns+1]) + + def removeRow(self, rowPosition): + # remove widgets from table + for col in range(self.pm_noColumns + self.extraCols): + widget = self.pm_rows[rowPosition][col] + if widget: + self.remove(widget) + if self.pm_callbacks.has_key(widget): + widget.disconnect(self.pm_callbacks[widget]) + del self.pm_callbacks[widget] + + + # reposition existing rows in gtk.Table + self._moveRows(-1, rowPosition + 1) + # remove row from list of rows + del self.pm_rows[rowPosition] + + self._setMinusButtonSensitivity() + self.pm_noRows -= 1 + self.resize(self.pm_noRows, self.pm_noColumns + self.extraCols) + self._printDebugInfo() + + + def _createCallback(self, widget, rowPosition, callbackType = None, callbackMethod=None): + if callbackType: + self.pm_callbacks[widget] = widget.connect(callbackType, callbackMethod, rowPosition) + else: + name = widget.get_name() + if name == 'GtkComboBox': + self.pm_callbacks[widget] = widget.connect("changed", self.on_combobox_changed, rowPosition) + elif name == 'GtkEntry': + self.pm_callbacks[widget] = widget.connect("changed", self.on_entry_changed, rowPosition) + + + def _moveRows(self, adjustment, startRow, endRow = -1): + """ + Moves gtk.Table rows up or down according to adjustment (which MUST be -1 or 1). + + Starts at row startRow and ends at row endRow. If endRow == -1, then goes to last row in table. + Readjusts callbacks. + """ + if endRow == -1: + endRow = len(self.pm_rows) + for r in range(startRow, endRow): + if self.debug: + print "Row %s becomes row %s" % (self.pm_rows[r][self.pm_noColumns + 2].get_label(), r + adjustment) + self.pm_rows[r][self.pm_noColumns + 2].set_label(str(r + adjustment)) + + for col in range(self.pm_noColumns + self.extraCols): + widget = self.pm_rows[r][col] + if widget: + self.remove(widget) + widget.disconnect(self.pm_callbacks[widget]) + self.attach(widget, col, col+1, r + adjustment, r + adjustment + 1) + if col == self.pm_noColumns: + self._createCallback(widget, r + adjustment, 'clicked', self.on_minus_button_clicked) + elif col == self.pm_noColumns + 1: + self._createCallback(widget, r + adjustment, 'clicked', self.on_plus_button_clicked) + else: + self._createCallback(widget, r + adjustment) + + + def _printDebugInfo(self): + if self.debug: + print "\nRows in internal list: %s\nTable rows: %s" % \ + (len(self.pm_rows), self.pm_noRows) + + if len(self.pm_rows) <> self.pm_noRows: + print "|\n\\\n --> Unequal no. of rows" + + + + def attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions=gtk.EXPAND|gtk.FILL, + yoptions=gtk.SHRINK, xpadding=0, ypadding=0): + """ + Override base class attach method, to allow automatic shrinking of minus and plus buttons + """ + if left_attach >= self.pm_noColumns and left_attach <= self.pm_noColumns + 1: + # since we are adding plus or minus button, shrink the button + gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, gtk.SHRINK, gtk.SHRINK, xpadding, ypadding) + else: + gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding) + + + def insertAfter(self, rowPosition, row): + """ + Inserts row into the table at row following rowPosition + """ + + + #is table big enough? + self.checkTableRowsAndAdjust() + + #move (reattach) other widgets & readjust connect + self._moveRows(1, rowPosition + 1) + + # insert row + for col in range(self.pm_noColumns): + widget = row[col] + if widget: + self._createCallback(widget, rowPosition+1) + self.attach(widget, col, col+1, rowPosition+1, rowPosition+2) + + minus_button, plus_button = self._createMinusPlusButtons(rowPosition+1) + + row.append(minus_button) + row.append(plus_button) + self.attach(minus_button, self.pm_noColumns, self.pm_noColumns+1, rowPosition+1, rowPosition+2) + self.attach(plus_button, self.pm_noColumns+1, self.pm_noColumns+2, rowPosition+1, rowPosition+2) + + if self.debug: + label = gtk.Label(str(rowPosition+1)) + self.attach(label, self.pm_noColumns+2, self.pm_noColumns+3, rowPosition+1, rowPosition+2) + row.append(label) + + + for widget in row: + if widget: + widget.show() + + #adjust internal reference table + + self.pm_rows.insert(rowPosition + 1, row) + + self._setMinusButtonSensitivity() + + self._printDebugInfo() + + def checkTableRowsAndAdjust(self, noRowsToAdd=1, adjustRows=True): + noRowsOk = True + if len(self.pm_rows) + noRowsToAdd > self.pm_noRows: + if adjustRows: + extraRowsToAdd = len(self.pm_rows) + noRowsToAdd - self.pm_noRows + self.pm_noRows += extraRowsToAdd + self.resize(self.pm_noRows, self.pm_noColumns + self.extraCols) + else: + noRowsOk = False + return noRowsOk + + def getDefaultRow(self): + """ + Returns a list of default widgets to insert as a row into the table. + + Expected to be implemented in derived class. + """ + + return [None] * self.pm_noColumns + + def on_combobox_changed(self, widget, rowPosition): + """ + Callback for combobox that is expected to be implemented in derived class + """ + pass + + def on_entry_changed(self, widget, rowPosition): + """ + Callback for entry that is expected to be implemented in derived class + """ + pass + + def _debugButtonPressed(self, buttonText, rowPosition): + if self.debug: + t = datetime.datetime.now().strftime("%H:%M:%S") + print "\n****\n%s\n\n%s clicked at %s" %(t, buttonText, rowPosition) + + def on_minus_button_clicked(self, widget, rowPosition): + self._debugButtonPressed("Minus", rowPosition) + self.removeRow(rowPosition) + self.on_rowDeleted(rowPosition) + + def on_plus_button_clicked(self, widget, rowPosition): + self._debugButtonPressed("Plus", rowPosition) + self.insertAfter(rowPosition, self.getDefaultRow()) + self.on_rowAdded(rowPosition) + + def on_rowAdded(self, rowPosition): + """ + Expected to be implemented in derived class + """ + pass + + def on_rowDeleted(self, rowPosition): + """ + Expected to be implemented in derived class + """ + pass + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2af92b4 --- /dev/null +++ b/setup.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# -*- coding: latin1 -*- + +from distutils.core import setup +from distutils.command.install_data import install_data +from distutils.dep_util import newer +from distutils.log import info + +from rapid.config import version +import glob +import os + +name = 'rapid-photo-downloader' + +class InstallData(install_data): + """ This class is largely copied from setup.py in Terminator 0.8.1 by Chris Jones <cmsj@tenshu.net>""" + def run (self): + self.data_files.extend (self._compile_po_files ()) + install_data.run (self) + + def _compile_po_files (self): + data_files = [] + + PO_DIR = 'po' + for po in glob.glob (os.path.join (PO_DIR,'*.po')): + lang = os.path.basename(po[:-3]) + mo = os.path.join('build', 'mo', lang, '%s.mo' % name) + + directory = os.path.dirname(mo) + if not os.path.exists(directory): + info('creating %s' % directory) + os.makedirs(directory) + + if newer(po, mo): + # True if mo doesn't exist + cmd = 'msgfmt -o %s %s' % (mo, po) + info('compiling %s -> %s' % (po, mo)) + if os.system(cmd) != 0: + raise SystemExit('Error while running msgfmt') + + dest = os.path.dirname(os.path.join('share', 'locale', lang, 'LC_MESSAGES', '%s.mo' % name)) + data_files.append((dest, [mo])) + + return data_files + +package_data={'rapid': ['glade3/rapid.glade', 'glade3/rapid-photo-downloader-about.png', 'glade3/image-missing.svg']} + +setup(name=name, + version=version, + description='Rapid Photo Downloader for Linux', + license='GPL', + author='Damon Lynch', + author_email='damonlynch@gmail.com', + maintainer='Damon Lynch', + url='http://www.damonlynch.net/rapid', + long_description= +"""Rapid Photo Downloader is written by a photographer for +professional and amateur photographers. It can download photos +from multiple cameras, memory cards and Portable Storage Devices +simultaneously. It provides many options for subfolder creation, +image renaming and backup.""", + packages = ['rapid'], + package_data=package_data, + scripts=['rapid-photo-downloader'], + platforms=['linux'], + data_files=[ + ('share/applications', ['data/rapid-photo-downloader.desktop']), + ('share/pixmaps', ['data/icons/48x48/apps/rapid-photo-downloader.png', 'data/icons/rapid-photo-downloader.xpm']), + ('share/icons/hicolor/scalable/apps', glob.glob('data/icons/scalable/apps/*.svg')), + ('share/icons/hicolor/16x16/apps', glob.glob('data/icons/16x16/apps/*.png')), + ('share/icons/hicolor/22x22/apps', glob.glob('data/icons/22x22/apps/*.png')), + ('share/icons/hicolor/24x24/apps', glob.glob('data/icons/24x24/apps/*.png')), + ('share/icons/hicolor/48x48/apps', glob.glob('data/icons/48x48/apps/*.png')), + ], + cmdclass={'install_data': InstallData} +) |