diff options
author | Julien Valroff <julien@kirya.net> | 2011-04-29 18:38:10 +0200 |
---|---|---|
committer | Julien Valroff <julien@kirya.net> | 2011-04-29 18:38:10 +0200 |
commit | 890778d8bc097acb3b7cff0fd134c2fe89e22c78 (patch) | |
tree | 195e65c397ca43f2dc7a8851df32963dd2fa313f | |
parent | ab35ecfe638a0eb072a5669263a18a60ae1d6611 (diff) | |
parent | c0a71b15d1fc070d1a55ee94ed8a7bd81aa3608a (diff) |
Merge branch 'experimental'
65 files changed, 26301 insertions, 22303 deletions
@@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: rapid-photo-downloader -Version: 0.3.6 +Version: 0.4.0~rc1 Summary: Rapid Photo Downloader for Linux Home-page: http://www.damonlynch.net/rapid Author: Damon Lynch diff --git a/debian/changelog b/debian/changelog index 09c8fd7..ec54efa 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,31 @@ -rapid-photo-downloader (0.3.6-2) unstable; urgency=low +rapid-photo-downloader (0.4.0~rc1-1) experimental; urgency=low - * Update to new policy 3.9.2 (no changes needed) + * New upstream Release Candidate * Add menu file - * Update VCS fields - -- Julien Valroff <julien@debian.org> Sun, 24 Apr 2011 08:30:59 +0200 + -- Julien Valroff <julien@debian.org> Sat, 23 Apr 2011 09:21:23 +0200 + +rapid-photo-downloader (0.4.0~beta1-1) experimental; urgency=low + + * New upstream beta release + * Update to new policy 3.9.2 (no changes needed) + + -- Julien Valroff <julien@debian.org> Sat, 16 Apr 2011 16:39:37 +0200 + +rapid-photo-downloader (0.4.0~alpha4-1) experimental; urgency=low + + * New upstream alpha version + + -- Julien Valroff <julien@debian.org> Fri, 08 Apr 2011 07:09:56 +0200 + +rapid-photo-downloader (0.4.0~alpha1-1) experimental; urgency=low + + * New upstream alpha version: + + New user interface + + Improve speed + * Update dependencies for the new release + + -- Julien Valroff <julien@debian.org> Fri, 25 Mar 2011 22:10:10 +0100 rapid-photo-downloader (0.3.6-1) unstable; urgency=low diff --git a/debian/control b/debian/control index 27021c8..5c24cf1 100644 --- a/debian/control +++ b/debian/control @@ -20,13 +20,13 @@ Depends: ${python:Depends}, python-glade2 (>= 2.12), python-gconf (>= 2.18), python-gnome2 (>= 2.12), - python-pyexiv2 (>= 0.1.1), + python-pyexiv2 (>= 0.3), python-notify, librsvg2-common, gnome-icon-theme, - librsvg2-common -Recommends: python-imaging, - python-kaa-metadata, + librsvg2-common, + python-imaging +Recommends: python-kaa-metadata, python-hachoir-metadata, ffmpegthumbnailer Description: Photo downloader (importer) from cameras, memory cards other devices @@ -7,239 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" -"PO-Revision-Date: 2011-02-10 18:47+0000\n" -"Last-Translator: Kuvaly [LCT] <kuvaly@seznam.cz>\n" +"POT-Creation-Date: 2011-04-04 00:18-0500\n" +"PO-Revision-Date: 2011-04-09 18:48+0000\n" +"Last-Translator: Vlastimil Ott <vlastimil@e-ott.info>\n" "Language-Team: Czech <cs@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: 2011-03-20 22:12+0000\n" -"X-Generator: Launchpad (build 12617)\n" +"X-Launchpad-Export-Date: 2011-04-11 01:01+0000\n" +"X-Generator: Launchpad (build 12757)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:103 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "New York" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "Manila" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "Praha" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "Helsinki" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "Teherán" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "Paříž" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "Berlín" - -#: rapid/rapid.py:463 -msgid "Sydney" -msgstr "Sydney" - -#: rapid/rapid.py:464 -msgid "Budapest" -msgstr "Budapešť" - -#: rapid/rapid.py:464 -msgid "Rome" -msgstr "Řím" - -#: rapid/rapid.py:464 -msgid "Moscow" -msgstr "Moskva" - -#: rapid/rapid.py:464 -msgid "Delhi" -msgstr "Dílí" - -#: rapid/rapid.py:464 -msgid "Warsaw" -msgstr "Varšava" - -#: rapid/rapid.py:465 -msgid "Jakarta" -msgstr "Jakarta" - -#: rapid/rapid.py:465 -msgid "Madrid" -msgstr "Madrid" - -#: rapid/rapid.py:465 -msgid "Stockholm" -msgstr "Stockholm" - -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" -msgstr "Hodnota dnešní stahování je invalidní.\n" - -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" -msgstr "Resetování hodnoty na nulu.\n" - -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "Hodnota nastavení 'Začátek dne' je poškozena.\n" - -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" -msgstr "Resetování do půlnoci.\n" - -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" -msgstr "Chyba v nastavení přejmenování fotografií" - -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Promiňte, v nastavení je chyba:\n" - -#: rapid/rapid.py:609 -msgid "Resetting to default values." -msgstr "Resetování na výchozí hodnoty." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" -msgstr "Pracovní kód" - -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" -msgstr "Chyba v nastavení přejmenování videí" - -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" -msgstr "" - -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" -msgstr "" - -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" -msgstr "fotografie a videa" - -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 -msgid "photos" -msgstr "fotografie" - -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "Vyberte složku do které mají být obrázky staženy" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" -msgstr "Zvolte adresář do kterého se bude stahovat video" - -#: rapid/rapid.py:1055 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "" - -#: rapid/rapid.py:1077 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" - -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata 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:1198 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Příklad: %s</i>" - -#: rapid/rapid.py:1224 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"Hodnota Dnešní stahování není aktualizována, v současné době dochází ke " -"stažení" - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Hodnota Skladované číslo není aktualizována, v současné době dochází ke " -"stažení" - -#: rapid/rapid.py:1270 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" - -#. Preferences list is now empty -#: rapid/rapid.py:1275 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" -msgstr "fotografie" - -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" -msgstr "video" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -msgid "externaldrive1" -msgstr "externídisk1" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1529 -msgid "externaldrive2" -msgstr "externídisk2" - -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" -msgstr "fotografie či videa" - -#: rapid/rapid.py:1556 -msgid "videos" -msgstr "videa" - -#: rapid/rapid.py:1568 +#: rapid/rapid.py:108 #, python-format msgid "" "%(date)s\n" @@ -248,1385 +31,1386 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1570 +#: rapid/rapid.py:110 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1573 -#, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" - -#: rapid/rapid.py:1580 +#: rapid/rapid.py:113 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" -msgstr "podsložka a název souboru" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:144 +msgid "Device" +msgstr "Zařízení" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" -msgstr "název souboru" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:158 +msgid "Size" +msgstr "Velikost" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" -msgstr "podsložka" +#: rapid/rapid.py:161 +msgid "Download Progress" +msgstr "Průběh stahování" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 +#: rapid/rapid.py:974 msgid "scanning..." msgstr "skenování..." -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" -msgstr "Následující cesta stahování nemůže být vytvořena:\n" - -#: rapid/rapid.py:1819 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 -msgid "Download cannot proceed" -msgstr "Stahování nemůže pokračovat" - -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." -msgstr "Vyskytla se chyba v nastavení programu." - -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Prosím zkontrolujte nastavení, restartujte program a zkuste to znovu." - -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2019 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Sken zařízení kompletní: nalezeno %(number)s %(filetypes)s na %(device)s" - -#: rapid/rapid.py:2026 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "" -"Sken zařízení kompletní: žádné %(filetypes)s nebyly nalezeny na %(device)s" +#: rapid/rapid.py:1678 +msgid "Download" +msgstr "Stáhnout" -#. 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:2047 -msgid "The device can now be safely removed" -msgstr "Zařízení nyní nemůže být bezpečně vymazáno" +#: rapid/rapid.py:1681 +msgid "Pause" +msgstr "Pozastavit" -#: rapid/rapid.py:2053 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s staženo" - -#: rapid/rapid.py:2056 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "%(noFiles)s %(filetypes)s nebyly staženy" - -#: rapid/rapid.py:2059 rapid/rapid.py:5901 -msgid "warnings" -msgstr "varování" - -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" -msgstr "chyby" - -#: rapid/rapid.py:2091 -#, python-format -msgid "Source: %s\n" -msgstr "Zdroj: %s\n" - -#: rapid/rapid.py:2093 -#, python-format -msgid "Device: %s\n" -msgstr "Zařízení: %s\n" - -#: rapid/rapid.py:2094 -#, python-format -msgid "Destination: %s" -msgstr "Destinace: %s" - -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" -msgstr "Nelze vytvořit dočasný stahovací adresář" - -#: rapid/rapid.py:2098 -msgid "Error:" -msgstr "Chyba:" - -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" -msgstr "Cesta zálohování neexistuje" - -#: rapid/rapid.py:2123 -#, python-format -msgid "The path %s could not be created" -msgstr "Cesta %s nemohla být vytvořena" - -#: rapid/rapid.py:2124 -msgid "No backups can occur" -msgstr "" - -#: rapid/rapid.py:2153 +#: rapid/rapid.py:1794 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" msgstr "" -"Zdroj: %(source)s\n" -"Destinace: %(destination)s\n" -"%(problem)s" +"Následující složky jsou neplatné:\n" +"%(folder1)s\n" +"%(folder2)s" -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 +#: rapid/rapid.py:1797 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" -msgstr "" -"Zdroj: %(source)s\n" -"Destinace: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "" - -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" - -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" +"This download folder is invalid:\n" +"%s" msgstr "" +"Následující složka je neplatná:\n" +"%s" -#: rapid/rapid.py:2260 rapid/rapid.py:2659 -#, python-format -msgid "Source: %(source)s" -msgstr "Zdroj: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "Nový den začal - resetování 'Dnešní stahování' sekvenční číslo" - -#: rapid/rapid.py:2529 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Záloha %(file_type)s již existuje" - -#: rapid/rapid.py:2533 -#, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "Záloha %(file_type)s přepsána" - -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "%(file_type)s nebylo zálohováno do %(volume)s" - -#: rapid/rapid.py:2539 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "%(file_type)s nebyl zálohován" - -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" -msgstr "Chyba zálohování" - -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Adresář destinace nelze vytvořit: %(directory)s\n" - -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" -msgstr "Chyba: %(inst)s" - -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "Toto %(file_type)s nebylo zálohováno." - -#: rapid/rapid.py:2595 rapid/rapid.py:2645 -#, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Chyba: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2658 -#, python-format -msgid "%(file_type)s could not be backed up" -msgstr "" - -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" -msgstr "" - -#: rapid/rapid.py:2663 -msgid "A backup location was not found" -msgstr "Umístění zálohy nenalezeno" - -#: rapid/rapid.py:2717 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." -msgstr "" - -#: rapid/rapid.py:2813 -#, python-format -msgid "Download has started from %s" -msgstr "Stahování začalo z %s" - -#: rapid/rapid.py:2817 -#, python-format -msgid "Attempting to download %s files" -msgstr "" +#: rapid/rapid.py:1798 +msgid "Download cannot proceed" +msgstr "Stahování nemůže pokračovat" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 +#: rapid/rapid.py:1957 #, python-format msgid "%(number)s of %(total)s %(filetypes)s" -msgstr "" - -#: rapid/rapid.py:2913 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" -msgstr "" - -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" -msgstr "Nelze odstranit fotografie či video ze zařízení" - -#: rapid/rapid.py:2939 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" -msgstr "" -"Fotografie: %(source)s\n" -"Chyba: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" -msgstr "Fotografie: %(source)s" - -#: rapid/rapid.py:2945 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "Odstraněno %(number)i %(filetypes)s ze zařízení" - -#: rapid/rapid.py:2958 -#, python-format -msgid "Download complete from %s" -msgstr "Stahování kompletní 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:3073 rapid/rapid.py:3542 -msgid "Device" -msgstr "Zařízení" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" -msgstr "Velikost" +msgstr "%(number)s z celkem %(total)s %(filetypes)s" -#: rapid/rapid.py:3081 -msgid "Download Progress" -msgstr "Průběh stahování" - -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" -msgstr "Stahování z kamer" - -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" -msgstr "" - -#: rapid/rapid.py:3176 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." -msgstr "" - -#: rapid/rapid.py:3190 -msgid "_Show this message again" -msgstr "_Zobrazit tuto zprávu znovu" - -#: rapid/rapid.py:3225 -msgid "Device Detected" -msgstr "Zařízení detekováno" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "" -"Should this device or partition be used to download photos or videos from?" -msgstr "" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 -msgid "_Remember this choice" -msgstr "_Zapamatovat si tuto volbu" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s vybráno pro stažení" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" -msgstr "Toto zařízení či oddíl bude vždy použito pro stažení" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s odmítnuto jako stahovací zařízení" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" -msgstr "Toto zařízení či oddíl nebude použito pro stažení" - -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" -msgstr "Odstranit všechny pracovní kódy?" - -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" -msgstr "Chcete odstranit všechny pracovní kódy?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" -msgstr "Vložte pracovní kód" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" -msgstr "" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" -msgstr "Vložte nový pracovní kód" - -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" -msgstr "Pracovní kód:" - -#: rapid/rapid.py:3425 -msgid "Job Code entered" -msgstr "Pracovní kód vložen" - -#: rapid/rapid.py:3427 -msgid "Job Code not entered" -msgstr "Pracovní kód nebyl vložen" - -#: rapid/rapid.py:3477 -msgid "Status" -msgstr "Stav" - -#: rapid/rapid.py:3485 -msgid "Type" -msgstr "Typ" - -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" -msgstr "Fotografie" - -#: rapid/rapid.py:3496 -msgid "File" -msgstr "Soubor" - -#: rapid/rapid.py:3511 -msgid "Job Code" -msgstr "Pracovní kód" - -#: rapid/rapid.py:3521 -msgid "Date" -msgstr "Datum" - -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" -msgstr "Jméno souboru" - -#: rapid/rapid.py:3564 -msgid "Path" -msgstr "Cesta" - -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s bylo úspěšně staženo" - -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s nebylo staženo" - -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s bylo staženo s varováními" - -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" -msgstr "" +#: rapid/rapid.py:2302 rapid/preferencesdialog.py:825 rapid/rpdfile.py:120 +msgid "photos" +msgstr "fotografie" -#: rapid/rapid.py:3982 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "" +#: rapid/rapid.py:2304 rapid/rpdfile.py:115 +msgid "videos" +msgstr "videa" -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s je připraveno ke stažení" +#: rapid/rapid.py:2308 +msgid "Free space:" +msgstr "Volné místo:" -#: rapid/rapid.py:3986 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2320 #, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "" +msgid "(%(file_type)s)" +msgstr "(%(file_type)s)" -#: rapid/rapid.py:3988 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2324 #, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s bude staženo s varováními" +msgid "%(free)s %(file_type)s" +msgstr "%(free)s %(file_type)s" -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s nelze stáhnout" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2329 +msgid "; " +msgstr "; " -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2334 +msgid "." +msgstr "." -#: rapid/rapid.py:5034 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2340 #, python-format -msgid "%(free)s available" -msgstr "%(free)s je k dispozici" +msgid "%(free)s free" +msgstr "%(free)s volné" #. user manually specified backup location -#: rapid/rapid.py:5040 +#: rapid/rapid.py:2346 #, python-format msgid "Backing up to %(path)s" msgstr "Zálohování %(path)s" -#: rapid/rapid.py:5045 +#: rapid/rapid.py:2351 #, python-format msgid "%(freespace)s. %(backuppaths)s." -msgstr "" +msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" - -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" -msgstr "" +#: rapid/rapid.py:2479 rapid/rpdfile.py:247 +msgid "Photo" +msgstr "Fotografie" -#: rapid/rapid.py:5067 +#: rapid/rapid.py:2481 rapid/rpdfile.py:267 msgid "Video" msgstr "Video" -#: rapid/rapid.py:5074 +#: rapid/rapid.py:2490 #, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "" +msgid "%(file_type)s download folder does not exist" +msgstr "%(file_type)s složka neexistuje" -#: rapid/rapid.py:5083 +#: rapid/rapid.py:2492 rapid/rapid.py:2506 rapid/rapid.py:2519 #, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "" +msgid "Folder: %s" +msgstr "Složka: %s" -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" - -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" -msgstr "Problém se stahovací složkou" - -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" -msgstr "Problém se složkamy stahování" - -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." -msgstr "Některé nastavení bylo resetováno." - -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" -msgstr "" - -#: rapid/rapid.py:5149 +#: rapid/rapid.py:2504 #, python-format -msgid "Prompting whether to use %s" -msgstr "Výzva pro použití %s" - -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" -msgstr "Výzva pro pracovní kód" - -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Výzva k pracovnímu kódu již existuje, nevyzívejte znovu" - -#: rapid/rapid.py:5197 -msgid "Starting downloads" -msgstr "Stahování začíná" - -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "Stahování začne po vložení pracovního kódu" +msgid "%(file_type)s download folder is invalid" +msgstr "%(file_type)s složka je neplatná" -#: rapid/rapid.py:5248 +#: rapid/rapid.py:2517 #, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5253 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5257 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5262 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5287 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" -msgstr "" -"Novější verze této aplikace na tomto počítači již byla spuštěna.\n" -"\n" - -#: rapid/rapid.py:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"Nastavení programu se zdá být validní, ale zkontrolujte bezpečnou opravnou " -"operaci." - -#: rapid/rapid.py:5291 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "Promiňte, nastavení je invalidní a muselo být resetováno." - -#: rapid/rapid.py:5292 -msgid "Warning:" -msgstr "Varování:" - -#: rapid/rapid.py:5297 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." -msgstr "" -"Tato verze tohoto programu již na tomto počítači byla nainstalována. " -"Kontrola nastavení." - -#: rapid/rapid.py:5304 -msgid "Preferences were modified." -msgstr "Nastavení bylo modifikováno." - -#: rapid/rapid.py:5305 -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 "" -"Tato verze programu používá jiné nastavení než ta stará. Vaše nastavení bylo " -"aktualizováno.\n" -"\n" -"Prosím zkontrolujte bezpečnou opravnou operaci." +msgid "%(file_type)s download folder is not writable" +msgstr "%(file_type)s do složky nelze zapisovat" -#: rapid/rapid.py:5309 -msgid "No preferences needed to be changed." -msgstr "Žádné nastavení nebylo změněno." - -#: rapid/rapid.py:5311 -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 "" -"Tato verze programu využívá uživatelsky jiné nastavení než ta předchozí. " -"Některé nastavení je invalidní a nelze aktualizovat. Je tedy resetováno." - -#: rapid/rapid.py:5321 -msgid "Problem using pynotify." -msgstr "Problém používání pynotify." - -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." -msgstr "Přijetí schopností pynotify serveru selhalo." - -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Varování: notifikační server prostředí plochy je špatně nakonfigurován." - -#: rapid/rapid.py:5396 -msgid "and" -msgstr "a" - -#: rapid/rapid.py:5401 -msgid "Using backup devices" -msgstr "Používání zálohovacích zařízení" - -#: rapid/rapid.py:5403 -msgid "Using backup device" -msgstr "Používání zálohovacího zařízení" - -#: rapid/rapid.py:5405 -msgid "No backup devices detected" -msgstr "Zálohovací zařízení nebylo detekováno" - -#: rapid/rapid.py:5455 rapid/rapid.py:5617 -#, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Zařízení %(device)s (%(path)s) ignorováno" - -#: rapid/rapid.py:5576 -#, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Detekováno %(device)s s %(path)s cestami" - -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" -msgstr "Automatický start stahování je povolen" - -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" -msgstr "Automatický start stahování je zakázán" - -#: rapid/rapid.py:5635 -msgid "Using manually specified path" -msgstr "Používání manuálně specifikované cesty" - -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" -msgstr "" - -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" -msgstr "" - -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" -msgstr "Všechna stahování kompletní" - -#: rapid/rapid.py:5837 -msgid "MB/s" -msgstr "MB/s" - -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" -msgstr "Zbývá 1 sekunda" - -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" -msgstr "Zbývá %i sekund" - -#: rapid/rapid.py:5851 -msgid "About 1 minute remaining" -msgstr "Zbývá 1 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:5856 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Zbývá %(minutes)i:%(seconds)02i minut" - -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "" - -#: rapid/rapid.py:5878 rapid/rapid.py:5890 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s staženo" - -#: rapid/rapid.py:5884 rapid/rapid.py:5896 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "" - -#: rapid/rapid.py:6070 -msgid "_Resume" -msgstr "_Pokračovat" - -#: rapid/rapid.py:6073 -msgid "_Download All" -msgstr "_Stáhnout vše" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" -msgstr "_Pozastavit" - -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." -msgstr "" - -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." -msgstr "Nastavení zálohy bylo změněno." - -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." -msgstr "" - -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." -msgstr "" - -#: rapid/rapid.py:6422 -msgid "Goodbye" -msgstr "Hezký den" +#: rapid/rapid.py:2592 +msgid "Thumbnails" +msgstr "Náhledy" #. 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:6433 +#: rapid/rapid.py:2633 #, python-format msgid "" "display program information on the command line as the program runs " "(default: %default)" msgstr "zobrazit informace o programu na příkazové řádce (default: %default)" -#: rapid/rapid.py:6434 +#: rapid/rapid.py:2634 msgid "display debugging information when run from the command line" -msgstr "" +msgstr "Zobrazit ladicí informace při spuštění z příkazové řádky" -#: rapid/rapid.py:6435 +#: rapid/rapid.py:2635 msgid "only output errors to the command line" msgstr "pouze výstup chyb do příkazové řádky" #. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6437 +#: rapid/rapid.py:2637 msgid "list photo and video file extensions the program recognizes and exit" -msgstr "" +msgstr "zobrazit přípony souborů, které program rozpozná, a skončit" -#: rapid/rapid.py:6438 +#: rapid/rapid.py:2638 msgid "reset all program settings and preferences and exit" -msgstr "" +msgstr "resetovat nastavení programu a skončit" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:2651 msgid "Photos:" msgstr "Fotografie:" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:2651 msgid "Videos:" msgstr "Videa:" -#: rapid/rapid.py:6457 +#: rapid/rapid.py:2656 #, python-format msgid "and %s" msgstr "a %s" -#: rapid/rapid.py:6465 +#: rapid/rapid.py:2664 msgid "All settings and preferences have been reset" +msgstr "Všechna nastavení a předvolby byly nastaveny na výchozí hodnoty" + +#: rapid/rapid.py:2673 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." msgstr "" +"Není možné stahovat video.\n" +"Ke stahování videa jsou nutné balíčky hachoir-metadata a kaa-metadata pro " +"Python." -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" -msgstr "Používání" +#: rapid/copyfiles.py:136 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:346 +#, python-format +msgid "" +"%(problem)s\n" +"File: %(file)s" +msgstr "" +"%(problem)s\n" +"Soubor: %(file)s" -#: rapid/rapid.py:6474 -msgid "\n" -msgstr "\n" +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Zařízení detekováno" -#. this application is already running -#: rapid/rapid.py:6498 -#, python-format -msgid "%s is already running" -msgstr "%s není připraven k používání" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "Nacházejí se na tomto zařízení fotografie nebo videa ke stažení?" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "_Zapamatovat si tuto volbu" -#: rapid/renamesubfolderprefs.py:192 +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Datum a čas" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Text" -#: rapid/renamesubfolderprefs.py:195 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Jméno souboru" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Metadata" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Sekvence" -#: rapid/renamesubfolderprefs.py:199 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:550 +msgid "Job code" +msgstr "Pracovní kód" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Datum obrázku" -#: rapid/renamesubfolderprefs.py:200 +#: rapid/generatenameconfig.py:151 msgid "Video date" -msgstr "" +msgstr "Datum videa" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Dnes" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Včerejšek" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 +#: rapid/generatenameconfig.py:155 msgid "Download time" msgstr "Čas stahování" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 +#: rapid/generatenameconfig.py:157 msgid "Name + extension" msgstr "Jméno + koncovka" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:208 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Název" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 +#: rapid/generatenameconfig.py:161 msgid "Extension" msgstr "Koncovka" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Číslo obrázku" -#: rapid/renamesubfolderprefs.py:213 +#: rapid/generatenameconfig.py:164 msgid "Video number" msgstr "Číslo videa" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Clona" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 +#: rapid/generatenameconfig.py:168 msgid "ISO" msgstr "ISO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:219 +#: rapid/generatenameconfig.py:170 msgid "Exposure time" msgstr "Čas expozice" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:221 +#: rapid/generatenameconfig.py:172 msgid "Focal length" msgstr "Vzdálenost ohniska" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:223 +#: rapid/generatenameconfig.py:174 msgid "Camera make" msgstr "Vytvoření fotoaparátu" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:225 +#: rapid/generatenameconfig.py:176 msgid "Camera model" msgstr "Druh fotoaparátu" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:227 +#: rapid/generatenameconfig.py:178 msgid "Short camera model" msgstr "Krátký druh kamery" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:229 +#: rapid/generatenameconfig.py:180 msgid "Hyphenated short camera model" msgstr "Model kamery v označení odděleném pomlčkou" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:231 +#: rapid/generatenameconfig.py:182 msgid "Serial number" msgstr "Sériové číslo" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:233 +#: rapid/generatenameconfig.py:184 msgid "Shutter count" msgstr "Číslo snímku" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:235 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Vlastníkovo jméno" -#: rapid/renamesubfolderprefs.py:236 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Kodek" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Šířka" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Výška" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Délka" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Snímková hodnota" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 +#: rapid/generatenameconfig.py:193 msgid "Downloads today" msgstr "Dnešní stahování" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:244 +#: rapid/generatenameconfig.py:195 msgid "Session number" msgstr "Číslo této relace" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:246 +#: rapid/generatenameconfig.py:197 msgid "Subfolder number" msgstr "Číslo podsložky" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:248 +#: rapid/generatenameconfig.py:199 msgid "Stored number" msgstr "Uskladněné číslo" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:250 +#: rapid/generatenameconfig.py:201 msgid "Sequence letter" msgstr "Zpráva sekvence" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:252 +#: rapid/generatenameconfig.py:203 msgid "All digits" msgstr "Všechny číslice" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:254 +#: rapid/generatenameconfig.py:205 msgid "Last digit" msgstr "Poslední číslice" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:256 +#: rapid/generatenameconfig.py:207 msgid "Last 2 digits" msgstr "Poslední 2 číslice" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:258 +#: rapid/generatenameconfig.py:209 msgid "Last 3 digits" msgstr "Poslední 3 číslice" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:260 +#: rapid/generatenameconfig.py:211 msgid "Last 4 digits" msgstr "Poslední 4 číslice" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:262 +#: rapid/generatenameconfig.py:213 msgid "Original Case" msgstr "Originální obal" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:264 +#: rapid/generatenameconfig.py:215 msgid "UPPERCASE" msgstr "Velká písmena (ABCDEFG)" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "Malá písmena (abcdefg)" -#: rapid/renamesubfolderprefs.py:267 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Jedna číslice" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Dvě číslice" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Tři číslice" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Čtyři číslice" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Pět číslic" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Šest číslic" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "Sedm číslic" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 +#: rapid/generatenameconfig.py:226 msgid "Subseconds" msgstr "Milisekundy" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "RRRRMMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 +#: rapid/generatenameconfig.py:230 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:281 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "RRMMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 +#: rapid/generatenameconfig.py:234 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:285 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "MMDDRRRR" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "MMDDRR" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "MMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "DDMMRRRR" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "DDMMRR" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "RRRR" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "RR" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "DD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "HHMMSS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "HHMM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "HH-MM-SS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "HH-MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "HH" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "MM (minuty)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "SS" -#: rapid/renamesubfolderprefs.py:800 +#: rapid/preferencesdialog.py:371 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Nastavení podsložky nemělo začít %s" + +#: rapid/preferencesdialog.py:373 #, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Nastavení podsložky nemělo končit %s" + +#: rapid/preferencesdialog.py:377 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "Nastavení podsložky by nemělo obsahovat dvě %s za sebou" + +#: rapid/preferencesdialog.py:390 rapid/preferencesdialog.py:673 +msgid "Remove all Job Codes?" +msgstr "Odstranit všechny pracovní kódy?" + +#: rapid/preferencesdialog.py:407 rapid/preferencesdialog.py:690 +msgid "Should all Job Codes be removed?" +msgstr "Chcete odstranit všechny pracovní kódy?" + +#: rapid/preferencesdialog.py:437 +msgid "Error in Photo Rename preferences" +msgstr "Chyba v nastavení přejmenování fotografií" + +#: rapid/preferencesdialog.py:618 +msgid "Error in Video Rename preferences" +msgstr "Chyba v nastavení přejmenování videí" + +#: rapid/preferencesdialog.py:639 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Chyba v nastavení složek pro stahování fotek" + +#: rapid/preferencesdialog.py:656 +msgid "Error in Video Download Subfolders preferences" +msgstr "Chyba v nastavení složek pro stahování videí" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:715 +msgid "Enter a Job Code" +msgstr "Vložte pracovní kód" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:732 +msgid "Enter a new Job Code, or select a previous one" +msgstr "Vložte nový štítek nebo vyberte nějaký existující" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:735 +msgid "Enter a new Job Code" +msgstr "Vložte nový pracovní kód" + +#: rapid/preferencesdialog.py:740 +msgid "Job Code:" +msgstr "Pracovní kód:" + +#: rapid/preferencesdialog.py:823 rapid/rpdfile.py:110 +msgid "photos and videos" +msgstr "fotografie a videa" + +#: rapid/preferencesdialog.py:992 +msgid "Select a folder to download photos to" +msgstr "Vyberte složku do které mají být obrázky staženy" + +#: rapid/preferencesdialog.py:1010 +msgid "Select a folder to download videos to" +msgstr "Zvolte adresář do kterého se bude stahovat video" + +#: rapid/preferencesdialog.py:1101 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Vyberte složku, která obsahuje %(file_types)s" + +#: rapid/preferencesdialog.py:1123 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "Vyberte složku, do které se bude zálohovat %(file_types)s" + +#. 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/preferencesdialog.py:1207 msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" msgstr "" -"Klíč nastavení '%(key)s' je invalidní\n" -"Předpokládáno %(value)s" +"<i><b>Varování:</b> Není k dispozici dostatečný počet metadat, aby bylo " +"možné vytvořit celé jméno. Použijte prosím pro vytvoření jména jiné " +"možnosti.</i>" -#: rapid/renamesubfolderprefs.py:807 +#: rapid/preferencesdialog.py:1258 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Varování:</b> Není k dispozici dostatečný počet metadat, aby bylo " +"možné vytvořit složky. Použijte prosím pro vytvoření jména jiné " +"možnosti.</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/preferencesdialog.py:1261 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Příklad: %s</i>" + +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1351 #, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "Hodnota nastavení '%(value)s' je invalidní" +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." +msgstr "" +"Parametry pro vytvoření složky %(filetype)s jsou neplatné a nelze je " +"použít.\n" +"Použijí se výchozí hodnoty." + +#. check subfolder preferences for bad values +#: rapid/preferencesdialog.py:1365 rapid/rpdfile.py:122 rapid/rpdfile.py:246 +msgid "photo" +msgstr "fotografie" + +#: rapid/preferencesdialog.py:1366 rapid/rpdfile.py:117 rapid/rpdfile.py:266 +msgid "video" +msgstr "video" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1637 +msgid "externaldrive1" +msgstr "externídisk1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1639 +msgid "externaldrive2" +msgstr "externídisk2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "New York" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manila" -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" -msgstr "Tato nastavení nejsou správně utvořena:" +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Praha" + +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinki" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Teherán" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Paříž" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlín" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sydney" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Budapešť" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Řím" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moskva" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Dílí" -#: rapid/renamesubfolderprefs.py:1524 +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Varšava" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jakarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madrid" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Stockholm" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:339 +msgid "subfolder" +msgstr "podsložka" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:337 +msgid "filename" +msgstr "název souboru" + +#: rapid/problemnotification.py:80 #, python-format -msgid "Subfolder preferences should not start with a %s" -msgstr "Nastavení podsložky nemělo začít %s" +msgid "Date time value %s appears invalid." +msgstr "Hodnota pro datum nebo čas %s je neplatná." + +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "Jméno souboru neobsahuje příponu." -#: rapid/renamesubfolderprefs.py:1526 +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "Jméno souboru neobsahuje číselnou hodnotu." + +#: rapid/problemnotification.py:84 #, python-format -msgid "Subfolder preferences should not end with a %s" -msgstr "Nastavení podsložky nemělo končit %s" +msgid "Error generating component %s." +msgstr "Chyba při vytváření části %s." -#: rapid/renamesubfolderprefs.py:1530 +#. a generic problem +#: rapid/problemnotification.py:86 #, python-format -msgid "Subfolder preferences should not contain two %s one after the other" -msgstr "Nastavení podsložky by nemělo obsahovat dvě %s za sebou" +msgid "%(filetype)s metadata cannot be read" +msgstr "Metadata %(filetype)s nelze načíst." -#: rapid/glade3/rapid.glade.h:1 +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" +msgstr "Nelze vytvořit %(filetype)s %(area)s" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "Při kopírování %(filetype)s došlo k chybě." + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "%(filetype)s a již existuje" + +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." +msgstr "" +"%(filetype)s nelze zálohovat, protože nebylo nalezeno vhodné umístění." + +#: rapid/problemnotification.py:102 +#, python-format +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." +msgstr "" +"%(image1)s vytvořen %(image1_date)s v %(image1_time)s a %(image2)s " +"%(image2_date)s v %(image2_time)s." + +#: rapid/problemnotification.py:103 +#, python-format +msgid "%(filetype)s was already downloaded" +msgstr "%(filetype)s byl už stažen" + +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." +msgstr "" +"Existující %(filetype)s byl naposledy změněn %(date)s v %(time)s. Byl " +"přidán jedinečný identifikátor '%(identifier)s'." + +#: rapid/problemnotification.py:108 +#, python-format +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "Existující %(filetype)s byl naposledy změněn %(date)s v %(time)s." + +#: rapid/problemnotification.py:109 +#, python-format +msgid "There is no data with which to name the %(filetype)s." +msgstr "Neexistují žádná data k pojmenování %(filetype)s." + +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" +msgstr "Chyba: %(errorno)s %(strerror)s" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "Metadata jsou pravděpodobně poškozená." + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "Jméno souboru, přípona a EXIF naznačují, že soubor byl již stažen." + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr " byl zálohován na %(volume)s" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr " byl zálohován na následující zařízení: " + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "%s, " + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "%(volumes)s a %(final_volume)s." + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" +"Byly nalezeny fotky se stejným jménem, ale rozdílným časem vzniku: " +"%(details)s" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "Došlo k chybě při zálohování na %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "Došlo k chybě při zálohování na %(volume)s." + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "Došlo k chybám při zálohování na následující zařízení: " + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "%(volume)s (%(inst)s), " + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "%(volume)s, " + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "%(volumes)s a %(volume)s (%(inst)s)." + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "%(volumes)s a %(volume)s." + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "Na zařízení %(volume)s už záloha existuje." + +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "Zálohy už existují, a to v těchto umístěních: " + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "Záloha na %(volume)s byla přepsána." + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "Zálohy na následujících zařízeních byly přepsány: " + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "Došlo k chybě při vytváření adresářů na %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "Došlo k chybě při vytváření adresářů na následujících zařízeních: " + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "%(previousproblem)s - kromě toho: %(newproblem)s" + +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr " Kromě toho došlo k dalším %(problems)s problémům." + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr " Kromě toho došlo k %(problem)s." + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "Metadata %(type)s chybí." + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "Následující metada chybí: " + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "%(missing_metadata_elements)s a %(final_missing_metadata_element)s." + +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "Problémy při vytváření názvů pro složky a soubory" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "Problém při vytváření názvů pro složky a soubory" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "Problémy při vytváření %s" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "Problém při vytváření %s" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "%(filetype)s už existuje, ale byl zálohován" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "Při kopírování %(filetype)s došlo k chybě, ale záloha proběhla" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "Došlo k více problémům" + +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "Byly nalezeny fotky se stejným jménem, ale různým datem vzniku" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "chyby při zálohování" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "Chyby při zálohování" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "chyba při zálohování" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "Chyba při zálohování" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "%(previousproblem)s a %(backinguperror)s" + +#: rapid/rpdfile.py:112 +msgid "photos or videos" +msgstr "fotografie či videa" + +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" + +#: rapid/subfolderfile.py:194 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Zdroj: %(source)s\n" +"Destinace: %(destination)s" + +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" +msgstr "Fotka už byla stažena" + +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" +msgstr "Zdroj: %(source)s" + +#: rapid/subfolderfile.py:335 +msgid "subfolder and filename" +msgstr "podsložka a název souboru" + +#: rapid/subfolderfile.py:373 +msgid "Failed to create download subfolder" +msgstr "Nepodařilo se vytvořit podsložku" + +#: rapid/subfolderfile.py:374 +#, python-format +msgid "Path: %s" +msgstr "Cesta: %s" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "O aplikaci..." + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "Zaškrtnout všechny" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "Zaškrtnout všechny fotky" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "Zaškrtnout všechna videa" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Stahování / Pauza" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "Získat online pomoc..." + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "Darovat..." + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "Další soubor" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "Předchozí soubor" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "Konec" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "Aktualizovat" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "Nahlásit problém..." + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "Vybrat všechny se ští_tkem" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "Vybrat všechny _bez štítku" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "Přeložit tuto aplikaci..." + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "Odškrtnout všechny" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "Zaškrtnout _všechny" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Vyčistit kompletní stahování" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" +msgstr "_Stáhnout" + +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "_Záznam chyb" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Soubor" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "_Nápověda" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "Vybrat pro stažení" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Dejte příspěvek..." + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Vybrat" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Přeložit tuto aplikaci..." + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" +msgstr "_Odznačit vše" + +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "_Zobrazení" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " hh:mm" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "<b>Záloha</b>" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Kompaktibilita s jinými operačními systémy</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "<b>Zařízení</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Složka stahování</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Podsložky stahování</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Příklad</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Pracovní kódy</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "<b>Přejmenování fotografie</b>" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "<b>Konflikty jmen fotografií a videa</b>" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Automatizace programu</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Sekvenční čísla</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/media/externaldrive/Photos</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Příklad: /home/user/Pictures</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Příklad:</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Nový:</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 msgid "<i>Original:</i>" msgstr "<i>Originál:</i>" -#: rapid/glade3/rapid.glade.h:21 -msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" -msgstr "<span weight=\"bold\" size=\"x-large\">Automatizace</span>" - -#: rapid/glade3/rapid.glade.h:22 +#: rapid/glade3/prefs.ui.h:20 msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Záloha</span>\t" -#: rapid/glade3/rapid.glade.h:23 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Zařízení</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Chybová obsluha</span>" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Pracovní kódy</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Různé</span>" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Složky stahování fotografií</span>" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "" "<span weight=\"bold\" size=\"x-large\">Přejmenování fotografií</span>\t" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.h:27 msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Možnosti přejmenování</span>" -#: rapid/glade3/rapid.glade.h:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Složky stahování videa</span>" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Přejmenování videa</span>\t" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Přidat unikátní identifikátor" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Automatická detekce kapesních paměťových zařízení" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Automatická detekce zálohovacích zařízení" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Automaticky detekovat zařízení" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Automatizace" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Záloha" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Umístění zálohy:" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "Zálohovat fotografie a videa při stahování" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1634,29 +1418,27 @@ msgstr "" "Vyberte složku stahování. Podsložky pro stahované obrázky budou vytvořeny " "automaticky v této složce s použitím struktury specifikované níže." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." msgstr "" +"Vyberte složku pro stažení. Podsložky pro stažená videa jsou vytvořena " +"automaticky podle schématu, které si vytvoříte." -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Copyright Damon Lynch 2007-10" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Začátek dne:" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "Odstranit fotografie a videa ze zařízení po dokončení" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Zařízení" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1668,43 +1450,47 @@ msgid "" "setting it to PTP mode. If that is not possible, consider using a card " "reader.</i>" msgstr "" +"Zařízení obsahující fotky nebo videa jsou fotoaparáty, datové karty nebo " +"jiné datové nosiče.\n" +"Stahovat můžete z více zařízení zároveň, nebo můžete určit umístění na " +"disku.\n" +"<i>Pokud stahování přímo z fotoaparátu nefunguje nebo je pomalé, nastavte u " +"něj režim PTP. \n" +"Pokud to neumíte nebo to nejde, použijte raději čtečku karet.</i>" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Stahování / Pauza" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Složka stahování:" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Dnešní stahování:" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Chybová obsluha" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Chybový záznam" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" +msgstr "Ukončit program, i když stahování skončilo varováními nebo chybami" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" -msgstr "" +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" +msgstr "Ukončit program po stažení souborů" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" "Máte-li zapnutou automatickou detekci, vyberte přesnou lokaci zálohy." -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." msgstr "" +"Pokud zakážete automatickou detekci, vyberte umístění fotek a videí ručně" -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1714,122 +1500,64 @@ msgstr "" "budou z tohoto zařízení hledány obrázky. Na zařízeních s větší kapacitou to " "bude trvat déle." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Pracovní kódy" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Umístění:" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "Různé" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Přepsat" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "Složky fotografií" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "Přejmenování fotografií" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" -msgstr "" +msgstr "Název složky pro zálohu fotek" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Nastavení: Rapid Photo Downloader" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "O_dstranit vše" -#: rapid/glade3/rapid.glade.h:72 -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 je otevřený software; můžete ho redistribuovat a/nebo " -"modifikovat za podmínek GNU General Public License publikované Free Software " -"Foundation; ve verzi 2, nebo (podle vašich nároků) v jiné novější verzi.\n" -"\n" -"Rapid Photo Downloader je distribuován v naději že bude používán, ale BEZ " -"JAKÉKOLI ZÁRUKY; neposkytují se ani odvozené záruky PRODEJNOSTI anebo " -"VHODNOSTI PRO URČITÝ ÚČEL. Viz GNU General Public License pro více detailů.\n" -"\n" -"Měli byste obdržet kopii GNU General Public Licence spolu s Rapid Photo " -"Downloader. Pokud ji neobržíte napište na: Free Software Foundation, Inc, 51 " -"Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." - -#: rapid/glade3/rapid.glade.h:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Možnosti přejmenování" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Vybrat veškeré Foto_grafie" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Vybrat všechna Vi_dea" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "Vybr_at vše" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Vynechat" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Vynechat stahování" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " "python." msgstr "" +"Není možné stahovat video. Ke stahování videa jsou nutné balíčky <i>hachoir-" +"metadata</i> a <i>kaa-metadata</i> pro Python." -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1837,8 +1565,12 @@ msgid "" "used for backups. For each device you wish to use for backing up to, create " "a folder in it with one of these names.</i>" msgstr "" +"Vyberte složku, ve které jsou na zařízení uloženy zálohy. \n" +"<i>Poznámka: Podle toho se také pozná, zda je zařízení použito pro zálohy. " +"Na každém zařízení, které chcete pro zálohy použít, vytvořte složku s " +"některým jménem. </i>" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1846,143 +1578,104 @@ msgstr "" "Specifikujte čas ve 24 hodinovém formátu aby mohlo být resetováno sekvenční " "číslo v <i>Dnešní stahování</i>." -#: rapid/glade3/rapid.glade.h:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." msgstr "" +"Určete znaky, které se mohou objevit v názvech souborů, ale mohly by později " +"působit problémy" -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Start stahování při startu programu" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" -msgstr "" +msgstr "Začít stahovat hned po vložení zařízení" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Uskladněné číslo:" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Odstranit nekompatibilní znaky" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Synchronizovat sekvenční čísla RAW + JPEG" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" -msgstr "" +msgstr "Po stažení souborů odpojit zařízení" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" -msgstr "" +msgstr "Složky pro videa" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" -msgstr "" +msgstr "Přejmenovat videa" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" -msgstr "" +msgstr "Název složky pro zálohu videí" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." msgstr "" +"Pokud má fotka nebo video stejný název jako již existující soubor, vyberte, " +"zda se má stahování přeskočit, nebo přejmenovat." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." msgstr "" +"Vyberte, zda při zálohování přepsat na cílovém zařízení soubor se stejným " +"jménem, nebo jeho zálohování přeskočit." -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." msgstr "" +"Při stahování můžete fotky a videa zálohovat na více umístění, např. na " +"externí disky." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Přidat..." -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Vyčistit kompletní stahování" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Zařízení" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "_Záznam chyb" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Soubor" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "_Název souboru" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Nápověda online..." - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "_Nápověda" - -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Dejte příspěvek..." - -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Cesta" - -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "_Náhled" - -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Ohlásit problém..." - -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Vybrat" - -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "_Velikost" - -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Přeložit tuto aplikaci..." - -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Typ" - -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "_Zobrazení" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Importovat fotky a videa spolehlivě" #~ msgid "Error in Image Rename preferences" #~ msgstr "Chyba v nastavení přejmenovávání obrázků." +#~ msgid "Resetting to default values." +#~ msgstr "Resetování na výchozí hodnoty." + #~ msgid "Select an image folder" #~ msgstr "Vyberte složku obrázků" #~ msgid "Select a folder in which to backup images" #~ msgstr "Vyberte složku do které má být uložena záloha obrázků" +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Prosím zkontrolujte nastavení, restartujte program a zkuste to znovu." + +#~ msgid "There is an error in the program preferences." +#~ msgstr "Vyskytla se chyba v nastavení programu." + #~ msgid "Image filename could not be generated" #~ msgstr "Název obrázku nemohl být vygenerován" @@ -2013,9 +1706,18 @@ msgstr "_Zobrazení" #~ msgid "Unique identifier '%s' added" #~ msgstr "Unikátní identifikátor '%s' přidán" +#~ msgid "Backing up error" +#~ msgstr "Chyba zálohování" + #~ msgid "The image was not copied." #~ msgstr "Obrázek nebyl okopírován." +#~ msgid "warnings" +#~ msgstr "varování" + +#~ msgid "errors" +#~ msgstr "chyby" + #~ msgid "Backup device missing" #~ msgstr "Zálohovací zařízení chybí" @@ -2028,6 +1730,15 @@ msgstr "_Zobrazení" #~ msgid "Image already exists" #~ msgstr "Obrázek neexistuje" +#~ msgid "Starting downloads" +#~ msgstr "Stahování začíná" + +#~ msgid "Preferences were modified." +#~ msgstr "Nastavení bylo modifikováno." + +#~ msgid "and" +#~ msgstr "a" + #~ msgid "images skipped" #~ msgstr "obrázky přeskočeny" @@ -2037,12 +1748,30 @@ msgstr "_Zobrazení" #~ msgid "images downloaded" #~ msgstr "obrázky staženy" +#~ msgid "_Pause" +#~ msgstr "_Pozastavit" + +#~ msgid "Using" +#~ msgstr "Používání" + #~ msgid "Download copying error" #~ msgstr "Chyba kopírování obrázků" +#~ msgid "MB/s" +#~ msgstr "MB/s" + +#~ msgid "All downloads complete" +#~ msgstr "Všechna stahování kompletní" + +#~ msgid "_Report a Problem..." +#~ msgstr "_Ohlásit problém..." + #~ msgid "_Photos" #~ msgstr "_Fotografie" +#~ msgid "_Get Help Online..." +#~ msgstr "_Nápověda online..." + #~ msgid "_Thumbnails" #~ msgstr "_Náhledy" @@ -2067,9 +1796,26 @@ msgstr "_Zobrazení" #~ msgid "This device has no images to download from." #~ msgstr "Toto zařízení nemá žádné obrázky pro stažení." +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Stahování začalo z %s" + +#, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Stahování kompletní z %s" + #~ msgid "Thumbnail cannot be displayed" #~ msgstr "Náhled nemůže být zobrazen" +#~ msgid "Job Code entered" +#~ msgstr "Pracovní kód vložen" + +#~ msgid "No backup devices detected" +#~ msgstr "Zálohovací zařízení nebylo detekováno" + +#~ msgid " " +#~ msgstr " " + #~ msgid "<b>Image Rename</b>" #~ msgstr "<b>Přejmenování obrázku</b>" @@ -2098,9 +1844,16 @@ msgstr "_Zobrazení" #~ msgid "Preferences were changed." #~ msgstr "Nastavení změněno" +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s není připraven k používání" + #~ msgid "<b>Image Name Conflicts</b>" #~ msgstr "<b>Konflikt jmen obrázků</b>" +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "<span weight=\"bold\" size=\"x-large\">Automatizace</span>" + #~ msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>" #~ msgstr "<span weight=\"bold\" size=\"x-large\">Složka stahování</span>" @@ -2113,6 +1866,34 @@ msgstr "_Zobrazení" #~ msgid "Image Devices" #~ msgstr "Obrázková zařízení" +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Promiňte, v nastavení je chyba:\n" + +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Resetování do půlnoci.\n" + +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "Hodnota nastavení 'Začátek dne' je poškozena.\n" + +#~ msgid "Warning:" +#~ msgstr "Varování:" + +#~ msgid "Some preferences will be reset." +#~ msgstr "Některé nastavení bylo resetováno." + +#~ msgid "No preferences needed to be changed." +#~ msgstr "Žádné nastavení nebylo změněno." + +#~ msgid "Problem using pynotify." +#~ msgstr "Problém používání pynotify." + +#, python-format +#~ msgid "About %(minutes)i:%(seconds)02i minutes remaining" +#~ msgstr "Zbývá %(minutes)i:%(seconds)02i minut" + +#~ msgid "About 1 minute remaining" +#~ msgstr "Zbývá 1 minuta" + #~ msgid "<b>Missing Backup Devices</b>" #~ msgstr "<b>Chybějící zálohovací zařízení</b>" @@ -2132,12 +1913,59 @@ msgstr "_Zobrazení" #~ "Vyberte zda má být přeskočeno stahování obrázku nebo přidejte unikátní " #~ "identifikátor." +#~ msgid "Automation" +#~ msgstr "Automatizace" + #~ msgid "Automatically detect image devices" #~ msgstr "Automatická detekce obrázkových zařízení" #~ msgid "Exit program after completion of successful download" #~ msgstr "Odejít z programu když bude stahování hotovo" +#~ msgid "Error Log" +#~ msgstr "Chybový záznam" + +#~ 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 je otevřený software; můžete ho redistribuovat a/nebo " +#~ "modifikovat za podmínek GNU General Public License publikované Free Software " +#~ "Foundation; ve verzi 2, nebo (podle vašich nároků) v jiné novější verzi.\n" +#~ "\n" +#~ "Rapid Photo Downloader je distribuován v naději že bude používán, ale BEZ " +#~ "JAKÉKOLI ZÁRUKY; neposkytují se ani odvozené záruky PRODEJNOSTI anebo " +#~ "VHODNOSTI PRO URČITÝ ÚČEL. Viz GNU General Public License pro více detailů.\n" +#~ "\n" +#~ "Měli byste obdržet kopii GNU General Public Licence spolu s Rapid Photo " +#~ "Downloader. Pokud ji neobržíte napište na: Free Software Foundation, Inc, 51 " +#~ "Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA." + +#~ msgid "" +#~ "A newer version of this program was previously run on this computer.\n" +#~ "\n" +#~ msgstr "" +#~ "Novější verze této aplikace na tomto počítači již byla spuštěna.\n" +#~ "\n" + +#, python-format +#~ msgid "About %i seconds remaining" +#~ msgstr "Zbývá %i sekund" + +#~ msgid "About 1 second remaining" +#~ msgstr "Zbývá 1 sekunda" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2196,10 +2024,29 @@ msgstr "_Zobrazení" #~ "Obrázek: %(image)s\n" #~ "Problém: %(problem)s" +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "Promiňte, nastavení je invalidní a muselo být resetováno." + +#~ msgid "" +#~ "This version of the program is newer than the previously run version. " +#~ "Checking preferences." +#~ msgstr "" +#~ "Tato verze tohoto programu již na tomto počítači byla nainstalována. " +#~ "Kontrola nastavení." + +#~ msgid "Automatically start download is false" +#~ msgstr "Automatický start stahování je zakázán" + +#~ msgid "Automatically start download is true" +#~ msgstr "Automatický start stahování je povolen" + #, python-format #~ msgid "%(number)s of %(total)s images copied" #~ msgstr "%(number)s z %(total)s obrázků okopírováno" +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "Nový den začal - resetování 'Dnešní stahování' sekvenční číslo" + #~ msgid "" #~ "You can have your photos backed up to multiple locations as they are " #~ "downloaded, e.g. external hard drives." @@ -2207,6 +2054,25 @@ msgstr "_Zobrazení" #~ "Vy můžete vaše fotografie zálohovat do různých umístění a můžete je stahovat " #~ "na různé externí disky." +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "Stahování začne po vložení pracovního kódu" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Detekováno %(device)s s %(path)s cestami" + +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "Hodnota nastavení '%(value)s' je invalidní" + +#, python-format +#~ msgid "" +#~ "Preference key '%(key)s' is invalid.\n" +#~ "Expected one of %(value)s" +#~ msgstr "" +#~ "Klíč nastavení '%(key)s' je invalidní\n" +#~ "Předpokládáno %(value)s" + #~ msgid "" #~ "<i><b>Warning:</b> There is insufficient image metadata to fully generate " #~ "the name. Please use other renaming options.</i>" @@ -2236,6 +2102,9 @@ msgstr "_Zobrazení" #~ msgid "Start downloading upon image device insertion" #~ msgstr "Start stahování po vložení obrázkového zařízení" +#~ msgid "These preferences are not well formed:" +#~ msgstr "Tato nastavení nejsou správně utvořena:" + #~ msgid "Import your images efficiently and reliably" #~ msgstr "Importujte své obrázky efektivně a spolehlivě" @@ -2247,6 +2116,24 @@ msgstr "_Zobrazení" #~ "Metadata jsou základy pro generování podsložek / jmen obrázků.\n" #~ "Zdroj: %s" +#~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "Nastavení programu se zdá být validní, ale zkontrolujte bezpečnou opravnou " +#~ "operaci." + +#~ 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 "" +#~ "Tato verze programu používá jiné nastavení než ta stará. Vaše nastavení bylo " +#~ "aktualizováno.\n" +#~ "\n" +#~ "Prosím zkontrolujte bezpečnou opravnou operaci." + #, python-format #~ msgid "Error in date time component. Value %s appears invalid" #~ msgstr "Chyba v časovém komponentu. Hodnota %s se zdá invalidní" @@ -2254,11 +2141,17 @@ msgstr "_Zobrazení" #~ msgid "Subsecond metadata not present in image" #~ msgstr "Metadata subsekund neprezentují obrázek" +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Přijetí schopností pynotify serveru selhalo." + #~ msgid "Specify what to do when there are no backup devices." #~ msgstr "" #~ "Specifikujte co se má dít, když když nejsou nalezena žádná zálohovací " #~ "zařízení." +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Resetování hodnoty na nulu.\n" + #~ msgid "" #~ "The subfolder preferences entered are invalid and cannot be used.\n" #~ "They will be reset to their default values." @@ -2266,6 +2159,14 @@ msgstr "_Zobrazení" #~ "Vložené nastavení podsložky je invalidní a nelze použít.\n" #~ "Bylo tedy resetováno na výchozí hodnoty." +#~ 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 "" +#~ "Tato verze programu využívá uživatelsky jiné nastavení než ta předchozí. " +#~ "Některé nastavení je invalidní a nelze aktualizovat. Je tedy resetováno." + #~ msgid "Unmount (\"eject\") image device upon download completion" #~ msgstr "Odpojit (\"vysunout\") obrázkové zařízení po dokončení stahování" @@ -2283,6 +2184,9 @@ msgstr "_Zobrazení" #~ msgid "list image file extensions the program recognizes and exit" #~ msgstr "program rozpozná typy obrázkových souborů a ukončí" +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Hodnota dnešní stahování je invalidní.\n" + #~ msgid "" #~ "When backing up, choose whether to overwrite an image on the backup device " #~ "that has the same name, or skip backing it up." @@ -2326,15 +2230,49 @@ msgstr "_Zobrazení" #~ msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>" #~ msgstr "<span weight=\"bold\" size=\"x-large\">Obrázková zařízení</span>" +#~ msgid "Goodbye" +#~ msgstr "Hezký den" + #~ msgid "Image has no metadata" #~ msgstr "Obrázek nemá metadata" +#~ msgid "Job Code not entered" +#~ msgstr "Pracovní kód nebyl vložen" + #~ msgid "Enter a new job code." #~ msgstr "Vložte nový pracovní kód." +#~ msgid "Prompting for Job Code" +#~ msgstr "Výzva pro pracovní kód" + +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Výzva pro použití %s" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Výzva k pracovnímu kódu již existuje, nevyzívejte znovu" + +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Zařízení %(device)s (%(path)s) ignorováno" + +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s vybráno pro stažení" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s odmítnuto jako stahovací zařízení" + #~ msgid "Should this device or partition be used to download images from?" #~ msgstr "Máte zařízení či oddíl určený ke stažení?" +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "Toto zařízení či oddíl bude vždy použito pro stažení" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "Toto zařízení či oddíl nebude použito pro stažení" + #~ msgid "Enter a new job code, or select a previous one." #~ msgstr "Vložte nový pracovní kód, nebo vyberte předchozí." @@ -2365,6 +2303,9 @@ msgstr "_Zobrazení" #~ "Jméno podsložky nemohlo být řádně vygenerováno. Zkontrolujte, kde jsou " #~ "dostatečná metadata." +#~ msgid "The device can now be safely removed" +#~ msgstr "Zařízení nyní nemůže být bezpečně vymazáno" + #, python-format #~ msgid "Image: %(source)s" #~ msgstr "Chyba: %(source)s" @@ -2387,6 +2328,26 @@ msgstr "_Zobrazení" #~ "Obrázek: %(source)s\n" #~ "Chyba: %(errno)s %(strerror)s" +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Hodnota Skladované číslo není aktualizována, v současné době dochází ke " +#~ "stažení" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Hodnota Dnešní stahování není aktualizována, v současné době dochází ke " +#~ "stažení" + +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Copyright Damon Lynch 2007-10" + +#~ msgid "Using backup device" +#~ msgstr "Používání zálohovacího zařízení" + +#~ msgid "Using backup devices" +#~ msgstr "Používání zálohovacích zařízení" + #~ msgid "" #~ "Images detected with the same filenames, but taken at different times:" #~ msgstr "" @@ -2400,11 +2361,18 @@ msgstr "_Zobrazení" #~ "První obrázek: %(image1)s %(image1_date_time)s:%(image1_subseconds)s\n" #~ "Druhý obrázek: %(image2)s %(image2_date_time)s:%(image2_subseconds)s" +#~ msgid "Using manually specified path" +#~ msgstr "Používání manuálně specifikované cesty" + #, python-format #~ msgid "Image device: %s\n" #~ msgstr "Obrázkové zařízení: %s\n" #, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Zdroj: %s\n" + +#, python-format #~ msgid "" #~ "Source: %(source)s\n" #~ "Partially generated filename: %(newname)s\n" @@ -2416,6 +2384,24 @@ msgstr "_Zobrazení" #~ "Destinace: %(destination)s\n" #~ "Problém: %(problem)s" +#~ msgid "Error:" +#~ msgstr "Chyba:" + +#~ msgid "Could not create temporary download directory" +#~ msgstr "Nelze vytvořit dočasný stahovací adresář" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Destinace: %s" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Chyba: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Adresář destinace nelze vytvořit: %(directory)s\n" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2424,6 +2410,9 @@ msgstr "_Zobrazení" #~ "Zdroj: %(source)s\n" #~ "Destinace: %(destination)s\n" +#~ msgid "Problem with Download Folder" +#~ msgstr "Problém se stahovací složkou" + #~ msgid "Problem with Image Location Folder" #~ msgstr "Problém s lokací obrázkové složky" @@ -2441,6 +2430,11 @@ msgstr "_Zobrazení" #~ "Promiňte, stahovací složka existuje, ale nelze do ní zapisovat. Prosím " #~ "zkontrolujte oprávnění či nastavení programu" +#~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Varování: notifikační server prostředí plochy je špatně nakonfigurován." + #, python-format #~ msgid "" #~ "Sorry, this image location does not exist:\n" @@ -2458,16 +2452,206 @@ msgstr "_Zobrazení" #~ msgstr "%s(filetype)s nelze otevřít" #, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Sken zařízení kompletní: nalezeno %(number)s %(filetypes)s na %(device)s" + +#, python-format #~ msgid "%(filetype)s has no metadata" #~ msgstr "%(filetype)s nemá metadata" #, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "Záloha %(file_type)s přepsána" + +#, python-format #~ msgid "%(noFiles)s %(filetypes)s skipped" #~ msgstr "%(noFiles)s %(filetypes)s přeskočeno" #, python-format +#~ msgid "%(noFiles)s %(filetypes)s downloaded" +#~ msgstr "%(noFiles)s %(filetypes)s staženo" + +#~ msgid "A backup location was not found" +#~ msgstr "Umístění zálohy nenalezeno" + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Fotografie: %(source)s" + +#~ msgid "\n" +#~ msgstr "\n" + +#, python-format #~ msgid "Could not open %(filetype)s" #~ msgstr "Nemohu otevřít %(filetype)s" +#, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Záloha %(file_type)s již existuje" + +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Zařízení: %s\n" + +#, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "%(file_type)s nebyl zálohován" + #~ msgid "No backup device was automatically detected" #~ msgstr "Automaticky nebylo detekováno žádné zálohovací zařízení" + +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Nelze odstranit fotografie či video ze zařízení" + +#~ msgid "_Size" +#~ msgstr "_Velikost" + +#~ msgid "_Type" +#~ msgstr "_Typ" + +#~ msgid "_Device" +#~ msgstr "_Zařízení" + +#~ msgid "_Filename" +#~ msgstr "_Název souboru" + +#~ msgid "_Path" +#~ msgstr "_Cesta" + +#~ msgid "_Preview" +#~ msgstr "_Náhled" + +#, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "Toto %(file_type)s nebylo zálohováno." + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Chyba: %(inst)s" + +#~ msgid "Downloading From Cameras" +#~ msgstr "Stahování z kamer" + +#~ msgid "Date" +#~ msgstr "Datum" + +#~ msgid "File" +#~ msgstr "Soubor" + +#~ msgid "Status" +#~ msgstr "Stav" + +#~ msgid "Type" +#~ msgstr "Typ" + +#~ msgid "_Show this message again" +#~ msgstr "_Zobrazit tuto zprávu znovu" + +#~ msgid "Path" +#~ msgstr "Cesta" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s nebylo staženo" + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s bylo úspěšně staženo" + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s bylo staženo s varováními" + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s je připraveno ke stažení" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s nelze stáhnout" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s bude staženo s varováními" + +#~ msgid "Problem with Download Folders" +#~ msgstr "Problém se složkamy stahování" + +#, python-format +#~ msgid "%(free)s available" +#~ msgstr "%(free)s je k dispozici" + +#, python-format +#~ msgid "%(filetype)s downloaded" +#~ msgstr "%(filetype)s staženo" + +#~ msgid "Backup preferences were changed." +#~ msgstr "Nastavení zálohy bylo změněno." + +#~ msgid "_Resume" +#~ msgstr "_Pokračovat" + +#~ msgid "_Download All" +#~ msgstr "_Stáhnout vše" + +#~ msgid "Select _All" +#~ msgstr "Vybr_at vše" + +#~ msgid "Select All Vi_deos" +#~ msgstr "Vybrat všechna Vi_dea" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Vybrat veškeré Foto_grafie" + +#, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "" +#~ "Sken zařízení kompletní: žádné %(filetypes)s nebyly nalezeny na %(device)s" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Cesta %s nemohla být vytvořena" + +#~ msgid "Backup path does not exist" +#~ msgstr "Cesta zálohování neexistuje" + +#, python-format +#~ msgid "%(noFiles)s %(filetypes)s failed to download" +#~ msgstr "%(noFiles)s %(filetypes)s nebyly staženy" + +#~ msgid "The following download path could not be created:\n" +#~ msgstr "Následující cesta stahování nemůže být vytvořena:\n" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "%(file_type)s nebylo zálohováno do %(volume)s" + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Zdroj: %(source)s\n" +#~ "Destinace: %(destination)s\n" +#~ "%(problem)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Fotografie: %(source)s\n" +#~ "Chyba: %(errno)s %(strerror)s" + +#~ msgid "Job Code" +#~ msgstr "Pracovní kód" + +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "Odstraněno %(number)i %(filetypes)s ze zařízení" @@ -7,251 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" -"PO-Revision-Date: 2011-01-14 11:05+0000\n" +"POT-Creation-Date: 2011-04-10 19:59-0500\n" +"PO-Revision-Date: 2011-04-12 12:28+0000\n" "Last-Translator: Eg <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: 2011-03-20 22:12+0000\n" -"X-Generator: Launchpad (build 12617)\n" +"X-Launchpad-Export-Date: 2011-04-21 06:12+0000\n" +"X-Generator: Launchpad (build 12883)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:104 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "New York" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "Manila" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "Prag" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "Helsinki" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "Teheran" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "Paris" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "Berlin" - -#: rapid/rapid.py:463 -msgid "Sydney" -msgstr "Sydney" - -#: rapid/rapid.py:464 -msgid "Budapest" -msgstr "Budapest" - -#: rapid/rapid.py:464 -msgid "Rome" -msgstr "Rom" - -#: rapid/rapid.py:464 -msgid "Moscow" -msgstr "Moskau" - -#: rapid/rapid.py:464 -msgid "Delhi" -msgstr "Delhi" - -#: rapid/rapid.py:464 -msgid "Warsaw" -msgstr "Warschau" - -#: rapid/rapid.py:465 -msgid "Jakarta" -msgstr "Jakarta" - -#: rapid/rapid.py:465 -msgid "Madrid" -msgstr "Madrid" - -#: rapid/rapid.py:465 -msgid "Stockholm" -msgstr "Stockholm" - -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" -msgstr "Anzahl der ungültigen Downloads von heute.\n" - -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" -msgstr "Wert wird auf Null zurückgesetzt.\n" - -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "Der Vorgabewert für 'Start des Tages' ist ungültig.\n" - -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" -msgstr "Die Zeit wird auf Mitternacht zurückgesetzt.\n" - -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" -msgstr "Fehler in den Vorgaben zur Umbennennung von Bildern" - -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Entschuldigung, diese Voreinstellungen enthalten einen Fehler:\n" - -#: rapid/rapid.py:609 -msgid "Resetting to default values." -msgstr "Die Voreinstellungen werden auf die Standardwerte zurückgesetzt." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" -msgstr "Auftragsbezeichnung" - -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" -msgstr "Fehler in den Vorgaben zur Umbennennung von Filmen" - -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" -msgstr "Fehler in den Vorgaben für Bilder-Downloadunterordner" - -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" -msgstr "Fehler in den Vorgaben zur Filme-Downloadunterordner" - -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" -msgstr "BIlder und Filme" - -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 -msgid "photos" -msgstr "Bilder" - -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "Wählen Sie ein Verzeichnis für den Download der Bilder" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" -msgstr "Wählen Sie einen Ordner für den Download von Filmen" - -#: rapid/rapid.py:1055 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Wählen Sie einen Ordner welcher %(file_types)s enthält" - -#: rapid/rapid.py:1077 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "" -"Wählen Sie einen Ordner in welchem die Sicherungskopie von %(file_types)s " -"erstellt werden soll" - -#. 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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" -"<i><b>Warnung:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" - -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" -msgstr "" -"<i><b>Warnung:</b> Die Metadaten sind unvollständig, die Unterordner können " -"nicht erstellt werden. Bitte verwenden Sie andere Einstellungen zur " -"Benennung der Unterordner.</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:1198 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Beispiel: %s</i>" - -#: rapid/rapid.py:1224 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"Der Wert für heutige Downloads wurde nicht aktualisiert, da gerade ein " -"Download stattfindet" - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Der Wert für gespeicherte Anzahl wurde nicht aktualisiert, da gerade ein " -"Download stattfindet" - -#: rapid/rapid.py:1270 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" -"Bei den %(filetype)s Unterordner Einstellungen wurden überflüssige Werte " -"entfernt." - -#. Preferences list is now empty -#: rapid/rapid.py:1275 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" -"Die eingegebenen Einstellungen für %(filetype)s Unterordner sind ungültig " -"und können nicht verwendet werden.\n" -"Sie werden auf die Standardwerte zurückgesetzt." - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" -msgstr "Bild" - -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" -msgstr "Film" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -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:1529 -msgid "externaldrive2" -msgstr "ExternesLaufwerk2" - -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" -msgstr "Bilder oder Filme" - -#: rapid/rapid.py:1556 -msgid "videos" -msgstr "Filme" - -#: rapid/rapid.py:1568 +#: rapid/rapid.py:109 #, python-format msgid "" "%(date)s\n" @@ -260,846 +31,263 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1570 +#: rapid/rapid.py:111 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1573 -#, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" - -#: rapid/rapid.py:1580 +#: rapid/rapid.py:114 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" -msgstr "Unterordner und Dateiname" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:148 +msgid "Device" +msgstr "Laufwerk" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" -msgstr "Dateiname" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:165 +msgid "Size" +msgstr "Grösse" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" -msgstr "Unterordner" +#: rapid/rapid.py:168 +msgid "Download Progress" +msgstr "Fortschritt im Download" + +#: rapid/rapid.py:312 +#, python-format +msgid "%(device)s did not unmount" +msgstr "%(device)s konnte nicht entfernt werden" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 +#: rapid/rapid.py:1091 msgid "scanning..." msgstr "Überprüfe Laufwerke ..." -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" -msgstr "Der folgende Downloadpfad konnte nicht erstellt werden::\n" - -#: rapid/rapid.py:1819 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 -msgid "Download cannot proceed" -msgstr "Der Download kann nicht weitergeführt werden" - -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." -msgstr "Fehler in den Programmvoreinstellungen." - -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Bitte überprüfen Sie die Voreinstellungen, starten Sie das Programm neu und " -"versuchen es erneut." - -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2019 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Durchsuchen der Laufwerke abgeschlossen: %(number)s %(filetypes)s gefunden " -"auf %(device)s" - -#: rapid/rapid.py:2026 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "" -"Durchsuchen der Laufwerke abgeschlossen: Keine %(filetypes)s gefunden auf " -"%(device)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:2047 -msgid "The device can now be safely removed" -msgstr "Das Laufwerk kann nun entfernt werden" - -#: rapid/rapid.py:2053 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s heruntergeladen" - -#: rapid/rapid.py:2056 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "%(noFiles)s %(filetypes)s konnten nicht heruntergeladen werden" - -#: rapid/rapid.py:2059 rapid/rapid.py:5901 -msgid "warnings" -msgstr "Warnungen" - -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" -msgstr "Fehler" +#: rapid/rapid.py:1807 +msgid "Download" +msgstr "Herunterladen" -#: rapid/rapid.py:2091 -#, python-format -msgid "Source: %s\n" -msgstr "Quelle: %s\n" - -#: rapid/rapid.py:2093 -#, python-format -msgid "Device: %s\n" -msgstr "Laufwerk: %s\n" +#: rapid/rapid.py:1810 +msgid "Pause" +msgstr "Anhalten" -#: rapid/rapid.py:2094 -#, python-format -msgid "Destination: %s" -msgstr "Ziel: %s" - -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" -msgstr "Temporäres Download-Verzeichnis konnte nicht erstellt werden" - -#: rapid/rapid.py:2098 -msgid "Error:" -msgstr "Fehler:" - -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" -msgstr "Der Pfad zum Sicherungsverzeichnis ist ungültig" - -#: rapid/rapid.py:2123 -#, python-format -msgid "The path %s could not be created" -msgstr "Der Pfad %s konnte nicht erstellt werden" - -#: rapid/rapid.py:2124 -msgid "No backups can occur" -msgstr "Es können keine Sicherungskopien erstellt werden" - -#: rapid/rapid.py:2153 +#: rapid/rapid.py:1912 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" msgstr "" -"Quelle: %(source)s\n" -"Ziel: %(destination)s\n" -"%(problem)s" +"Diese Download-Verzeichnisse sind ungültig:\n" +"%(folder1)s\n" +"%(folder2)s" -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 +#: rapid/rapid.py:1915 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" +"This download folder is invalid:\n" +"%s" msgstr "" -"Quelle: %(source)s\n" -"Ziel: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "Bitte überprüfen Sie Ihr System und versuchen Sie es erneut" +"Dieses Download-Verzeichnis ist ungültig:\n" +"%s" -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" -"Bilder mit gleichem Dateinamen aber unterschiedlichen Aufnahmezeiten gefunden" +#: rapid/rapid.py:1916 +msgid "Download cannot proceed" +msgstr "Der Download kann nicht weitergeführt werden" -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" -msgstr "Das Bild wurde bereits heruntergeladen" +#: rapid/rapid.py:2130 +msgid "About 1 second remaining" +msgstr "Etwa 1 Sekunde verbleibend" -#: rapid/rapid.py:2260 rapid/rapid.py:2659 +#: rapid/rapid.py:2132 #, python-format -msgid "Source: %(source)s" -msgstr "Quelle: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "" -"Ein neuer Tag hat begonnen - die Anzahl der 'Downloads Heute' wird " -"zurückgesetzt" +msgid "About %i seconds remaining" +msgstr "Etwa %i Sekunden verbleibend" -#: rapid/rapid.py:2529 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Sicherungskopie von %(file_type)s exisiert bereits" +#: rapid/rapid.py:2134 +msgid "About 1 minute remaining" +msgstr "Etwa 1 Minute verbleibend" -#: rapid/rapid.py:2533 +#. 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:2139 #, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "Sicherungskopie %(file_type)s wurde überschrieben" +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Etwa %(minutes)i:%(seconds)02i Minuten verbleibend" -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "%(file_type)s konnte nicht auf %(volume)s gesichert werden" +#: rapid/rapid.py:2151 rapid/preferencesdialog.py:822 rapid/rpdfile.py:110 +msgid "photos and videos" +msgstr "BIlder und Filme" -#: rapid/rapid.py:2539 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "%(file_type)s wurde nicht gesichert" +#: rapid/rapid.py:2153 rapid/rpdfile.py:112 +msgid "photos or videos" +msgstr "Bilder oder Filme" -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" -msgstr "Fehler beim Erstellen der Sicherungskopie" +#: rapid/rapid.py:2156 rapid/rapid.py:2661 rapid/rpdfile.py:115 +msgid "videos" +msgstr "Filme" -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Das Zielverzeichnis konnte nicht erstellt werden: %(directory)s\n" +#: rapid/rapid.py:2158 rapid/preferencesdialog.py:1371 rapid/rpdfile.py:117 +#: rapid/rpdfile.py:266 +msgid "video" +msgstr "Film" -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" -msgstr "Fehler: %(inst)s" +#: rapid/rapid.py:2161 rapid/rapid.py:2659 rapid/preferencesdialog.py:824 +#: rapid/rpdfile.py:120 +msgid "photos" +msgstr "Bilder" -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "%(file_type)s wurde nicht gesichert." +#. check subfolder preferences for bad values +#: rapid/rapid.py:2163 rapid/preferencesdialog.py:1370 rapid/rpdfile.py:122 +#: rapid/rpdfile.py:246 +msgid "photo" +msgstr "Bild" -#: rapid/rapid.py:2595 rapid/rapid.py:2645 +#: rapid/rapid.py:2188 #, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Fehler: %(errno)s %(strerror)s" +msgid "%(noFiles)s %(filetypes)s downloaded" +msgstr "%(noFiles)s %(filetypes)s heruntergeladen" -#: rapid/rapid.py:2658 +#: rapid/rapid.py:2192 #, python-format -msgid "%(file_type)s could not be backed up" -msgstr "%(file_type)s konnte nicht gesichert werden" - -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" -msgstr "Es wurde kein verwendbares Sicherungslaufwerk gefunden" +msgid "%(noFiles)s %(filetypes)s failed to download" +msgstr "%(noFiles)s %(filetypes)s konnten nicht heruntergeladen werden" -#: rapid/rapid.py:2663 -msgid "A backup location was not found" -msgstr "Es wurde kein Sicherungsverzeichnis gefunden" +#: rapid/rapid.py:2195 rapid/rapid.py:2247 +msgid "warnings" +msgstr "Warnungen" -#: rapid/rapid.py:2717 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." -msgstr "Das Laufwerk enthält keine %(types_searched_for)s zum Herunterladen" +#: rapid/rapid.py:2204 +msgid "All downloads complete" +msgstr "Alle Downloads sind abgeschlossen" -#: rapid/rapid.py:2813 +#: rapid/rapid.py:2210 rapid/rapid.py:2219 rapid/rapid.py:2228 +#: rapid/rapid.py:2237 rapid/rapid.py:2245 #, python-format -msgid "Download has started from %s" -msgstr "Der Download von %s hat begonnen" +msgid "%(number)s %(numberdownloaded)s" +msgstr "%(number)s %(numberdownloaded)s" -#: rapid/rapid.py:2817 +#: rapid/rapid.py:2212 rapid/rapid.py:2230 #, python-format -msgid "Attempting to download %s files" -msgstr "Versuche %s Dateien herunterzuladen" +msgid "%(filetype)s downloaded" +msgstr "%(filetype)s heruntergeladen" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 +#: rapid/rapid.py:2221 rapid/rapid.py:2239 #, python-format -msgid "%(number)s of %(total)s %(filetypes)s" -msgstr "%(number)s von %(total)s %(filetypes)s" +msgid "%(filetype)s failed to download" +msgstr "%(filetype)s konnten nicht heruntergeladen werden" -#: rapid/rapid.py:2913 +#. e.g.: 3 of 205 photos and videos (202 remaining) +#: rapid/rapid.py:2276 #, python-format msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" msgstr "%(number)s of %(total)s %(filetypes)s (%(remaining)s verbleibend)" -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" -msgstr "Es konnten von dem Laufwerk keine Bilder oder Filme gelöscht werden" - -#: rapid/rapid.py:2939 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" -msgstr "" -"Bild: %(source)s\n" -"Fehler: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" -msgstr "Bild: %(source)s" - -#: rapid/rapid.py:2945 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "%(number)i %(filetypes)s vom Laufwerk gelöscht" - -#: rapid/rapid.py:2958 -#, 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:3073 rapid/rapid.py:3542 -msgid "Device" -msgstr "Laufwerk" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" -msgstr "Grösse" - -#: rapid/rapid.py:3081 -msgid "Download Progress" -msgstr "Fortschritt im Download" - -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" -msgstr "Bilder werden von der Kamera heruntergeladen" - -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" -msgstr "" -"Das direkte Herunterladen von der Kamera kann unter Umständen schlecht oder " -"gar nicht funktionieren" - -#: rapid/rapid.py:3176 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." -msgstr "" -"Das Herunterladen über einen Kartenleser generell gut und ist normalerweise " -"auch viel schneller. Dies ist die dringend empfohlene Methode." - -#: rapid/rapid.py:3190 -msgid "_Show this message again" -msgstr "_Meldung erneut anzeigen" - -#: rapid/rapid.py:3225 -msgid "Device Detected" -msgstr "Laufwerk gefunden" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "" -"Should this device or partition be used to download photos or videos from?" -msgstr "" -"Soll dieses Laufwerk oder diese Partition zum Herunterladen von Bildern oder " -"Filmen verwendet werden?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 -msgid "_Remember this choice" -msgstr "_Auswahl merken" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s wurde zum Herunterladen ausgewählt" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" -msgstr "Von diesem Laufwerk oder dieser Partition wird immer heruntergeladen" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s wurde als Laufwerk zum Herunterladen abgelehnt" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" -msgstr "Von diesem Laufwerk oder dieser Partition wird nie heruntergeladen" - -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" -msgstr "Alle Auftragsbezeichnungen löschen?" - -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" -msgstr "Sollen alle Auftragsbezeichnungen gelöscht werden?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" -msgstr "Geben Sie eine Auftragsbezeichnung ein" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" -msgstr "" -"Geben Sie eine neue Auftragsbezeichung ein oder wählen Sie eine bestehende " -"aus" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" -msgstr "Geben Sie eine neue Auftragsbezeichung ein" - -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" -msgstr "Auftragsbezeichnung:" - -#: rapid/rapid.py:3425 -msgid "Job Code entered" -msgstr "Auftragsbezeichnung eingegeben" - -#: rapid/rapid.py:3427 -msgid "Job Code not entered" -msgstr "Keine Auftragsbezeichnung angegeben" - -#: rapid/rapid.py:3477 -msgid "Status" -msgstr "Status" - -#: rapid/rapid.py:3485 -msgid "Type" -msgstr "Typ" - -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" -msgstr "Bild" - -#: rapid/rapid.py:3496 -msgid "File" -msgstr "Datei" - -#: rapid/rapid.py:3511 -msgid "Job Code" -msgstr "Auftragsbezeichnung" - -#: rapid/rapid.py:3521 -msgid "Date" -msgstr "Datum" - -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" -msgstr "Dateiname" - -#: rapid/rapid.py:3564 -msgid "Path" -msgstr "Pfad" - -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s wurde erfolgreich heruntergeladen" - -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s wurde nicht heruntergeladen" - -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s wurde mit Warnungen heruntergeladen" - -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" -msgstr "" -"%(filetype)s wurde heruntergeladen, beim Erstellen der Sicherungskopie " -"traten aber Fehler auf" - -#: rapid/rapid.py:3982 +#. e.g.: 205 of 205 photos and videos +#: rapid/rapid.py:2283 #, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "" -"%(filetype)s wurde weder heruntergeladen noch wurde eine Sicherungskopie " -"erstellt" - -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s ist bereit zum Herunterladen" - -#: rapid/rapid.py:3986 -#, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "%(filetype)s wird weruntergeladen" - -#: rapid/rapid.py:3988 -#, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s wird mit Warnungen weruntergeladen" - -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s kann nicht heruntergeladen werden" - -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "" -"Geben Sie eine neue Auftragsbezeichnung ein und drücken Sie EINGABE oder " -"selektieren Sie eine bestehende Auftragsbezeichnung" +msgid "%(number)s of %(total)s %(filetypes)s" +msgstr "%(number)s von %(total)s %(filetypes)s" -#: rapid/rapid.py:5034 -#, python-format -msgid "%(free)s available" +#: rapid/rapid.py:2665 +msgid "Free space:" +msgstr "Freier Speicherplatz:" + +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2677 +#, python-format +msgid "(%(file_type)s)" +msgstr "(%(file_type)s)" + +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2681 +#, python-format +msgid "%(free)s %(file_type)s" +msgstr "%(free)s %(file_type)s" + +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2686 +msgid "; " +msgstr "; " + +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2691 +msgid "." +msgstr "." + +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2697 +#, python-format +msgid "%(free)s free" msgstr "%(free)s verfügbar" #. user manually specified backup location -#: rapid/rapid.py:5040 +#: rapid/rapid.py:2703 #, python-format msgid "Backing up to %(path)s" msgstr "Sicherungskopieren in %(path)s erstellen" -#: rapid/rapid.py:5045 +#: rapid/rapid.py:2708 #, python-format msgid "%(freespace)s. %(backuppaths)s." msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" -"Dieser Laufwerkspfad existiert nicht:\n" -"%(path)s\n" -"\n" -"Beheben Sie das Problem oder ändern Sie die Voreinstellungen." +#: rapid/rapid.py:2737 +msgid "Program preferences are invalid" +msgstr "Die Benutzervoreinstellungen sind ungültig" -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" -msgstr "Probleme mit dem Laufwerk oder Verzeichnis" +#: rapid/rapid.py:2842 rapid/rpdfile.py:247 +msgid "Photo" +msgstr "Bild" -#: rapid/rapid.py:5067 +#: rapid/rapid.py:2844 rapid/rpdfile.py:267 msgid "Video" msgstr "Film" -#: rapid/rapid.py:5074 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "Das %(file_type)s Downloadverzeichnis existiert nicht.\n" - -#: rapid/rapid.py:5083 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "" -"Das %(file_type)s Downloadverzeichnis existiert, ist aber schreibgeschützt.\n" - -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" -"Mit den Downloadverzeichnissen bestehen Probleme. Bitte beheben Sie diese " -"oder passen Sie die Voreinstellungen an.\n" -"\n" - -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" -msgstr "Problem mit dem Dowanloadverzeichnis" - -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" -msgstr "Probleme mit den Downloadverzeichnissen" - -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." -msgstr "Einige Voreinstellungen werden zurückgesetzt." - -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" -msgstr "" -"Eine Warnung betreffend das direkte Herunterladen von der Kamera wird " -"angezeigt" - -#: rapid/rapid.py:5149 -#, python-format -msgid "Prompting whether to use %s" -msgstr "Abfrage, ob %s zu benutzen ist" - -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" -msgstr "Frage nach der Auftragsbezeichnung" - -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Auftragsbezeichnung wurde schon abgefragt, nicht wieder fragen" - -#: rapid/rapid.py:5197 -msgid "Starting downloads" -msgstr "Beginne mit den Downloads" - -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "" -"Beginne mit den Dowaloads welche auf eine Auftragsbezeichnung gewartet haben" - -#: rapid/rapid.py:5248 +#: rapid/rapid.py:2853 #, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "%(folder)s für das Herunterladen der Bilder erstellt" +msgid "%(file_type)s download folder does not exist" +msgstr "%(file_type)s Download-Verzeichnis existiert nicht" -#: rapid/rapid.py:5253 +#: rapid/rapid.py:2855 rapid/rapid.py:2869 rapid/rapid.py:2882 #, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "" -"%(folder)s konnte als Standardverzeichnis zum Herunterladen der Bilder nicht " -"erstellt werden" +msgid "Folder: %s" +msgstr "Verzeichnis: %s" -#: rapid/rapid.py:5257 +#: rapid/rapid.py:2867 #, python-format -msgid "Creating video download folder %(folder)s" -msgstr "%(folder)s für das Herunterladen der Filme erstellt" +msgid "%(file_type)s download folder is invalid" +msgstr "%(file_type)s Download-Verzeichnis ist ungültig" -#: rapid/rapid.py:5262 +#: rapid/rapid.py:2880 #, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "" -"%(folder)s konnte als Standardverzeichnis zum Herunterladen der Filme nicht " -"erstellt werden" - -#: rapid/rapid.py:5287 -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:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"Die Programmvoreinstellungen scheinen gültig zu sein, aber bitte überprüfen " -"Sie diese, um einen problemlosen Programmablauf zu gewährleisten." - -#: rapid/rapid.py:5291 -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:5292 -msgid "Warning:" -msgstr "Warnung:" - -#: rapid/rapid.py:5297 -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." +msgid "%(file_type)s download folder is not writable" +msgstr "%(file_type)s Download-Verzeichnis ist schreibgeschützt" -#: rapid/rapid.py:5304 -msgid "Preferences were modified." -msgstr "Die Voreinstellungen wurden geändert." - -#: rapid/rapid.py:5305 -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:5309 -msgid "No preferences needed to be changed." -msgstr "Es mussten keine Voreinstellungen angepasst werden." - -#: rapid/rapid.py:5311 -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:5321 -msgid "Problem using pynotify." -msgstr "Bei der Verwendung von pynotify ist ein Problem aufgetreten." - -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." -msgstr "Die Werte des pynotify Servers konnten nicht abgefragt werden." - -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Warnung: Der Desktop-Benachrichtigungsdienst ist falsch konfiguriert." - -#: rapid/rapid.py:5396 -msgid "and" -msgstr "und" - -#: rapid/rapid.py:5401 -msgid "Using backup devices" -msgstr "Die Sicherungslaufwerke werden verwendet" - -#: rapid/rapid.py:5403 -msgid "Using backup device" -msgstr "Das Sicherungslaufwerk wird verwendet" - -#: rapid/rapid.py:5405 -msgid "No backup devices detected" -msgstr "Es wurden keine Sicherungslaufwerke gefunden" - -#: rapid/rapid.py:5455 rapid/rapid.py:5617 -#, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Laufwerk %(device)s (%(path)s) ignoriert" - -#: rapid/rapid.py:5576 -#, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Die %(device)s gefunden auf Pfad %(path)s" - -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" -msgstr "Der automatische Downloadbeginn ist eingeschaltet" - -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" -msgstr "Der automatische Downloadbeginn ist ausgeschaltet" - -#: rapid/rapid.py:5635 -msgid "Using manually specified path" -msgstr "Verwende den manuell eingegebenen Pfad" - -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" -msgstr "" -"Vorsicht: Vom Sicherungslaufwerk %(device)s findet ein Download statt" - -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" -msgstr "_Herunterladen ausgewählt" - -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" -msgstr "Alle Downloads sind abgeschlossen" - -#: rapid/rapid.py:5837 -msgid "MB/s" -msgstr "MB/s" - -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" -msgstr "Etwa 1 Sekunde verbleibend" - -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" -msgstr "Etwa %i Sekunden verbleibend" - -#: rapid/rapid.py:5851 -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:5856 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Etwa %(minutes)i:%(seconds)02i Minuten verbleibend" - -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" - -#: rapid/rapid.py:5878 rapid/rapid.py:5890 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s heruntergeladen" - -#: rapid/rapid.py:5884 rapid/rapid.py:5896 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "%(filetype)s konnten nicht heruntergeladen werden" - -#: rapid/rapid.py:6070 -msgid "_Resume" -msgstr "_Fortsetzen" - -#: rapid/rapid.py:6073 -msgid "_Download All" -msgstr "_Alle Herunterladen" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" -msgstr "_Pause" - -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." -msgstr "Die Benutzervorgaben für Quellaufwerke wurden geändert." - -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." -msgstr "Die Benutzervorgaben für Sicherungslaufwerke wurden geändert." - -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." -msgstr "Die Benutzervorgaben für Unterordner und Dateinamen wurden geändert." - -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." -msgstr "Die Benutzervorgaben für Downloadordner wurden geändert." - -#: rapid/rapid.py:6422 -msgid "Goodbye" -msgstr "Auf Wiedersehen" +#: rapid/rapid.py:2958 +msgid "Thumbnails" +msgstr "Vorschaubilder" #. 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:6433 +#: rapid/rapid.py:3005 #, python-format msgid "" "display program information on the command line as the program runs " @@ -1108,582 +296,1232 @@ msgstr "" "Zeige die Programminformationen an, wenn das Programm aus der Kommandozeile " "aufgerufen wurde (Voreinstellung: %default)" -#: rapid/rapid.py:6434 +#: rapid/rapid.py:3006 msgid "display debugging information when run from the command line" msgstr "" "Während des Ausführens von der Kommandozeile Debug-Informationen anzeigen" -#: rapid/rapid.py:6435 +#: rapid/rapid.py:3007 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:6437 +#: rapid/rapid.py:3009 msgid "list photo and video file extensions the program recognizes and exit" msgstr "" "Anzeigen der Dateitypen für Bilder und Filme anzeigen, welche das Programm " "erkennt und beenden" -#: rapid/rapid.py:6438 +#: rapid/rapid.py:3010 msgid "reset all program settings and preferences and exit" msgstr "Alle Einstellungen auf Standardwerte zurücksetzten und beenden" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:3023 msgid "Photos:" msgstr "Bilder:" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:3023 msgid "Videos:" msgstr "Filme:" -#: rapid/rapid.py:6457 +#: rapid/rapid.py:3028 #, python-format msgid "and %s" msgstr "und %s" -#: rapid/rapid.py:6465 +#: rapid/rapid.py:3036 msgid "All settings and preferences have been reset" msgstr "Alle Einstellungen wurden zurückgesetzt" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" -msgstr "Verwende" - -#: rapid/rapid.py:6474 -msgid "\n" -msgstr "\n" +#: rapid/rapid.py:3045 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." +msgstr "" +"Die Video-Download-Funktionalität ist deaktiviert.\n" +"Um diese zu aktivieren müssen zuerst die hachoir metadata und kaa metadata " +"Pakete für Python installiert werden." -#. this application is already running -#: rapid/rapid.py:6498 +#: rapid/copyfiles.py:142 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:332 rapid/subfolderfile.py:350 #, python-format -msgid "%s is already running" -msgstr "%s wird bereits ausgeführt" +msgid "" +"%(problem)s\n" +"File: %(file)s" +msgstr "" +"%(problem)s\n" +"Datei: %(file)s" -#: rapid/renamesubfolderprefs.py:192 +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Laufwerk gefunden" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "" +"Soll dieses Laufwerk oder diese Partition zum Herunterladen von Bildern oder " +"Filmen verwendet werden?" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "_Auswahl merken" + +#: rapid/downloadtracker.py:217 +msgid "MB/s" +msgstr "MB/s" + +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Datum Zeit" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Text" -#: rapid/renamesubfolderprefs.py:195 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Dateiname" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Metadaten" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Sequenzen" -#: rapid/renamesubfolderprefs.py:199 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:549 +msgid "Job code" +msgstr "Auftragsbezeichnung" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Bilddatum" -#: rapid/renamesubfolderprefs.py:200 +#: rapid/generatenameconfig.py:151 msgid "Video date" msgstr "Film Datum" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Heute" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Gestern" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 +#: rapid/generatenameconfig.py:155 msgid "Download time" msgstr "Download-Zeit" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 +#: rapid/generatenameconfig.py:157 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:208 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Name" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 +#: rapid/generatenameconfig.py:161 msgid "Extension" msgstr "Erweiterung" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Bildnummer" -#: rapid/renamesubfolderprefs.py:213 +#: rapid/generatenameconfig.py:164 msgid "Video number" msgstr "Film Nummer" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Blende" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 +#: rapid/generatenameconfig.py:168 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:219 +#: rapid/generatenameconfig.py:170 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:221 +#: rapid/generatenameconfig.py:172 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:223 +#: rapid/generatenameconfig.py:174 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:225 +#: rapid/generatenameconfig.py:176 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:227 +#: rapid/generatenameconfig.py:178 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:229 +#: rapid/generatenameconfig.py:180 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:231 +#: rapid/generatenameconfig.py:182 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:233 +#: rapid/generatenameconfig.py:184 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:235 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Name des Eigentümers" -#: rapid/renamesubfolderprefs.py:236 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Codec" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Breite" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Höhe" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Länge" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Bilder pro Sekunde" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 +#: rapid/generatenameconfig.py:193 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:244 +#: rapid/generatenameconfig.py:195 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:246 +#: rapid/generatenameconfig.py:197 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:248 +#: rapid/generatenameconfig.py:199 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:250 +#: rapid/generatenameconfig.py:201 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:252 +#: rapid/generatenameconfig.py:203 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:254 +#: rapid/generatenameconfig.py:205 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:256 +#: rapid/generatenameconfig.py:207 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:258 +#: rapid/generatenameconfig.py:209 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:260 +#: rapid/generatenameconfig.py:211 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:262 +#: rapid/generatenameconfig.py:213 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:264 +#: rapid/generatenameconfig.py:215 msgid "UPPERCASE" msgstr "GROSSBUCHSTABEN" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "kleinschreibung" -#: rapid/renamesubfolderprefs.py:267 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Eine Ziffer" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Zwei Ziffern" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Drei Ziffern" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Vier Ziffern" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Fünf Ziffern" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Sechs Ziffern" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "Sieben Ziffern" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 +#: rapid/generatenameconfig.py:226 msgid "Subseconds" msgstr "Hundertstelsekunden" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "JJJJMMTT" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 +#: rapid/generatenameconfig.py:230 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:281 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "JJMMTT" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 +#: rapid/generatenameconfig.py:234 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:285 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "MMTTJJJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "MMTTJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "MMTT" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "TTMMJJJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "TTMMJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "JJJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "JJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "TT" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "HHMMSS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "HHMM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "HH-MM-SS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "HH-MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "HH" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "MM (Minuten)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "SS" -#: rapid/renamesubfolderprefs.py:800 -#, python-format -msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" -msgstr "" -"Voreingestellter Schlüssel '%(key)s' ist ungültig.\n" -"Erwarteter Wert %(value)s" - -#: rapid/renamesubfolderprefs.py:807 -#, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "Voreingestellter Wert '%(value)s' ist ungültig" - -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" -msgstr "Diese Voreinstellungen sind falsch formatiert:" - -#: rapid/renamesubfolderprefs.py:1524 +#: rapid/preferencesdialog.py:370 #, python-format msgid "Subfolder preferences should not start with a %s" msgstr "Die Unterverzeichnisvoreinstellungen sollten nicht mit %s beginnen" -#: rapid/renamesubfolderprefs.py:1526 +#: rapid/preferencesdialog.py:372 #, python-format msgid "Subfolder preferences should not end with a %s" msgstr "Die Unterverzeichnisvoreinstellungen sollten nicht mit %s enden" -#: rapid/renamesubfolderprefs.py:1530 +#: rapid/preferencesdialog.py:376 #, python-format msgid "Subfolder preferences should not contain two %s one after the other" msgstr "" "Die Unterverzeichnisvoreinstellungen sollten nicht zwei %s nacheinander " "enthalten" -#: rapid/glade3/rapid.glade.h:1 +#: rapid/preferencesdialog.py:389 rapid/preferencesdialog.py:672 +msgid "Remove all Job Codes?" +msgstr "Alle Auftragsbezeichnungen löschen?" + +#: rapid/preferencesdialog.py:406 rapid/preferencesdialog.py:689 +msgid "Should all Job Codes be removed?" +msgstr "Sollen alle Auftragsbezeichnungen gelöscht werden?" + +#: rapid/preferencesdialog.py:436 +msgid "Error in Photo Rename preferences" +msgstr "Fehler in den Vorgaben zur Umbennennung von Bildern" + +#: rapid/preferencesdialog.py:617 +msgid "Error in Video Rename preferences" +msgstr "Fehler in den Vorgaben zur Umbennennung von Filmen" + +#: rapid/preferencesdialog.py:638 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Fehler in den Vorgaben für Bilder-Downloadunterordner" + +#: rapid/preferencesdialog.py:655 +msgid "Error in Video Download Subfolders preferences" +msgstr "Fehler in den Vorgaben zur Filme-Downloadunterordner" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:714 +msgid "Enter a Job Code" +msgstr "Geben Sie eine Auftragsbezeichnung ein" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:731 +msgid "Enter a new Job Code, or select a previous one" +msgstr "" +"Geben Sie eine neue Auftragsbezeichung ein oder wählen Sie eine bestehende " +"aus" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:734 +msgid "Enter a new Job Code" +msgstr "Geben Sie eine neue Auftragsbezeichung ein" + +#: rapid/preferencesdialog.py:739 +msgid "Job Code:" +msgstr "Auftragsbezeichnung:" + +#: rapid/preferencesdialog.py:915 +msgid "Job Code" +msgstr "Auftragsbezeichnung" + +#: rapid/preferencesdialog.py:997 +msgid "Select a folder to download photos to" +msgstr "Wählen Sie ein Verzeichnis für den Download der Bilder" + +#: rapid/preferencesdialog.py:1015 +msgid "Select a folder to download videos to" +msgstr "Wählen Sie einen Ordner für den Download von Filmen" + +#: rapid/preferencesdialog.py:1106 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Wählen Sie einen Ordner welcher %(file_types)s enthält" + +#: rapid/preferencesdialog.py:1128 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "" +"Wählen Sie einen Ordner in welchem die Sicherungskopie von %(file_types)s " +"erstellt werden soll" + +#. 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/preferencesdialog.py:1212 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Warnung:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" + +#: rapid/preferencesdialog.py:1263 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Warnung:</b> Die Metadaten sind unvollständig, die Unterordner können " +"nicht erstellt werden. Bitte verwenden Sie andere Einstellungen zur " +"Benennung der Unterordner.</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/preferencesdialog.py:1266 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Beispiel: %s</i>" + +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1356 +#, python-format +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." +msgstr "" +"Die eingegebenen Einstellungen für %(filetype)s Unterordner sind ungültig " +"und können nicht verwendet werden.\n" +"Sie werden auf die Standardwerte zurückgesetzt." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1642 +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/preferencesdialog.py:1644 +msgid "externaldrive2" +msgstr "ExternesLaufwerk2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "New York" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manila" + +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Prag" + +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinki" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Teheran" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Paris" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlin" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sydney" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Budapest" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Rom" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moskau" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Delhi" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Warschau" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jakarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madrid" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Stockholm" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:343 +msgid "subfolder" +msgstr "Unterordner" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:341 +msgid "filename" +msgstr "Dateiname" + +#: rapid/problemnotification.py:80 +#, python-format +msgid "Date time value %s appears invalid." +msgstr "Die Werte für Datum und Zeit %s scheinen ungültig zu sein." + +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "Der Dateinamen enthält keinen Dateitypen." + +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "Der Dateinamen enthält keine Zahlen." + +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." +msgstr "Fehler beim Erstellen von %s." + +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" +msgstr "%(filetype)s Metadaten können nicht gelesen werden" + +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" +msgstr "%(filetype)s %(area)s können nicht erstellt werden" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "Beim Kopieren von %(filetype)s ist ein Fehler aufgetreten" + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "%(filetype)s existiert bereits" + +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." +msgstr "" +"Von %(filetype)s konnte keine Sicherungskopie erstellt werden, da kein " +"entsprechenden Verzeichnis gefunden wurde." + +#: rapid/problemnotification.py:102 +#, python-format +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." +msgstr "" +"%(image1)s wurde am %(image1_date)s um %(image1_time)s und %(image2)s am " +"%(image2_date)s um %(image2_time)s aufgenommen." + +#: rapid/problemnotification.py:103 +#, python-format +msgid "%(filetype)s was already downloaded" +msgstr "%(filetype)s wurde bereits heruntergeladen" + +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." +msgstr "" +"Die existierende Datei %(filetype)s wurde zuletzt am %(date)s um %(time)s " +"modifiziert. Eine eindeutige Kennung '%(identifier)s' wurde angefügt." + +#: rapid/problemnotification.py:108 +#, python-format +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "" +"Die existierende Datei %(filetype)s wurde zuletzt am %(date)s um %(time)s " +"modifiziert." + +#: rapid/problemnotification.py:109 +#, python-format +msgid "There is no data with which to name the %(filetype)s." +msgstr "" +"Es existieren keine Daten um den Dateinamen zu erstellen %(filetype)s." + +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" +msgstr "Fehler: %(errorno)s %(strerror)s" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "Die Metadaten scheinen korrupt zu sein." + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "" +"Dateiname, Erweiterung und EXIF-Informationen zeigen an, dass das Bild schon " +"heruntergeladen wurde." + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr " Es wurde auf %(volume)s gesichert" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr " Es wurde auf diese Laufwerke gesichert: " + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "%s, " + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "%(volumes)s und %(final_volume)s." + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" +"Bilder mit identischen Dateinamen aber unterschiedlichen Aufnahmezeiten " +"gefunden: %(details)s" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "" +"Ein Fehler trat auf beim beim Erstellen der Sicherungskopien auf Laufwerk " +"%(volume)s: %(inst)s." + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "" +"Ein Fehler trat auf beim beim Erstellen der Sicherungskopien auf Laufwerk " +"%(volume)s." + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "" +"Fehler traten auf beim beim Erstellen der Sicherungskopien auf die folgenden " +"Laufwerke: " + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "%(volume)s (%(inst)s), " + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "%(volume)s, " + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "%(volumes)s und %(volume)s (%(inst)s)." + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "%(volumes)s und %(volume)s." + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "Sicherungskopie existiert bereits auf %(volume)s." + +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "Sicherungskopien existieren bereits auf den folgenden Laufwerken: " + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "Sicherungskopie überschrieben auf %(volume)s." + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "Sicherungskopien überschrieben auf den folgenden Laufwerken: " + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "Fehler beim Erstellen der Verzeichnisse auf %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "" +"Fehler beim Erstellen der Verzeichnisse auf den folgenden " +"Sicherungslaufwerken: " + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "%(previousproblem)s zusätzlich, %(newproblem)s" + +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr " Zustätzlich sind folgende Probleme aufgetreten %(problems)s." + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr " Zustätzlich ist folgendes Problem aufgetreten %(problem)s." + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "Die %(type)s Metadaten fehlen." + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "Die folgenden Metadaten fehlen: " + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "" +"%(missing_metadata_elements)s und %(final_missing_metadata_element)s." + +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "Probleme bei der Erstllung der Order und Dateinamen" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "Problem bei der Erstllung der Order und Dateinamen" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "Probleme bei der Erstllung von %s" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "Problem bei der Erstllung von %s" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "%(filetype)s existiert bereits, wurde aber gesichert" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "" +"Beim kopieren von %(filetype)s, ist ein Fehler aufgetreten, es wurde aber " +"gesichert" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "Mehrere Probleme sind aufgetreten" + +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "" +"Bilder mit gleichem Dateinamen aber unterschiedlichen Aufnahmezeiten gefunden" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "beim Erstellen der Sicherungskopieren sind Fehler aufgetreten" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "Beim Erstellen der Sicherungskopieren sind Fehler aufgetreten" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "beim Erstellen der Sicherungskopieren ist ein Fehler aufgetreten" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "Beim Erstellen der Sicherungskopieren ist ein Fehler aufgetreten" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "%(previousproblem)s, und %(backinguperror)s" + +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" + +#: rapid/subfolderfile.py:194 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Quelle: %(source)s\n" +"Ziel: %(destination)s" + +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" +msgstr "Das Bild wurde bereits heruntergeladen" + +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" +msgstr "Quelle: %(source)s" + +#: rapid/subfolderfile.py:339 +msgid "subfolder and filename" +msgstr "Unterordner und Dateiname" + +#: rapid/subfolderfile.py:377 +msgid "Failed to create download subfolder" +msgstr "Der Download-Unterordner konnte nicht erstellt werden" + +#: rapid/subfolderfile.py:378 +#, python-format +msgid "Path: %s" +msgstr "Pfad: %s" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "Über ..." + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "Alle auswählen" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "Alle Bilder auswählen" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "Alle Filme auswählen" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Download / Pause" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "Online Hilfe erhalten …" + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "Eine Spende machen ..." + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "Nächste Datei" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "Vorherige Datei" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "Programm beenden" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "Aktualisieren" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "Ein Problem melden …" + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "Alle mit Auftragsbezeichnung auswählen" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "Alle ohne Auftragsbezeichnung auswählen" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "Dieses Programm übersetzen ..." + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "Auswahl aufheben" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "_Alle auswählen" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Heruntergeladene Dateien nicht mehr anzeigen" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" +msgstr "_Herunterladen" + +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "_Fehlerprotokoll" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Datei" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "_Hilfe" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "_Datei herunterladen" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Machen Sie eine Spende" + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Auswahl" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Übersetzung der Applikation" + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" +msgstr "A_uswahl aufheben" + +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "_Ansicht" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " hh:mm" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "<b>Datensicherung</b>" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Kompatibilität mit anderen Betriebssystemen</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "<b>Laufwerke</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Download Verzeichnis</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Download Unterverzeichnis</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Beispiel</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Auftragsbezeichnungen</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "<b>Umbenennen von Bildern</b>" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "<b>Namenskonflikte Bilder und Filme</b>" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Programm Automatisierung</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Sequenznummern</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/medium/externeslaufwerk/Fotos</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Beispiel: /home/user/Bilder</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Beispiel:</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Neu:</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 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 +#: rapid/glade3/prefs.ui.h:20 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 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Laufwerke</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 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 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Auftragsbezeichnungen</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Verschiedenes</span>" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Bilder Download Ordner</span>" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Bilder Umbenennen</span>\t" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.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:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Film Download Ordner</span>" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Filme Umbenennen</span>\t" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Füge eine eindeutige Information hinzu" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Suche automatisch nach portablen Laufwerken" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Suche automatisch nach Backuplaufwerken" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Automatisch erkannte Laufwerke" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Automatisierung" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Datensicherung" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Ziel der Datensicherung" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "Sicherungskopien während dem Herunterladen erstellen" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1691,7 +1529,7 @@ msgstr "" "Wählen Sie das Downloadverzeichnis. Unterverzeichnisse werden je nach " "gewählten Voreinstellungen automatisch erzeugt." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." @@ -1699,24 +1537,20 @@ msgstr "" "Wählen Sie den Download Ordner. Unterordner für die Filme werden automatisch " "basierend auf der unten angefügten Struktur erstellt." -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Copyright Damon Lynch Oktober 2007-2010" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Beginn des Tages:" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" "Bilder und Filme nach vollständigem Download auf dem Laufwerk löschen" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Laufwerke" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1738,39 +1572,33 @@ msgstr "" "stellen Sie 'PTP Modus' ein. Sollte das nicht möglich sein, so verwenden Sie " "bitte Speicherkarten.</i>" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Download / Pause" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Downloadverzeichnis:" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Downloads heute:" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Fehlerbehandlung" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Fehlerprotokoll" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" +msgstr "Programm beenden auch wenn Fehler oder Warnungen aufgetreten sind" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" -msgstr "" -"Programm beenden falls das Herunterladen ohne Fehler oder Warnungen " -"abgeschlossen wird." +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" +msgstr "Programm beenden wenn alles Downloads abgeschlossen sind" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 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:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." @@ -1778,7 +1606,7 @@ msgstr "" "Falls Sie die automatische Erkennung von Laufwerken ausschalten, geben Sie " "bitte den genauen Pfad zu den Bildern oder Filmen an." -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1788,117 +1616,55 @@ msgstr "" "das gesamte Laufwerk nach Bildern durchsucht. Bei sehr grossen Datenträgern " "kann dies eine Weile dauern." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "Importieren Sie Ihre Bilder und Filme schnell und zuverlässig" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Auftragsbezeichnungen" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Ort:" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "Verschiedenes" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Überschreibe" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "Spalten anzeigen" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "Bilder Verzeichnisse" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "Bilder Umbenennen" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "Ordner für Sicherungskopien der Bilder:" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Voreinstellungen: Rapid Photo Downloader" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "Order anzeigen" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "_Alle entfernen" -#: rapid/glade3/rapid.glade.h:72 -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:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Optionen für die Umbenennung" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "Keine Auswahl" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Alle Bilder auswählen" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Alle Filme auswählen" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "Alle mit Auftragsbezeichnung auswählen" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "Alle ohne Auftragsbezeichnung auswählen" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "_Alles auswählen" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Überspringen" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Überspringe Download" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " @@ -1908,7 +1674,7 @@ msgstr "" "ermöglichen müssen Sie die beiden Pakete <i>hachoir metadata</i> und <i>kaa " "metadata</i> für Python installieren." -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1923,7 +1689,7 @@ msgstr "" "Sicherungskopien verwendet wird. Erstellen Sie auf jedem Laufwerk, welches " "für Sicherungskopien verwendet wird, einen Ordner mit diesem Namen.</i>" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1931,7 +1697,7 @@ 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:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." @@ -1939,44 +1705,44 @@ msgstr "" "Geben Sie ab, ob Zeichen in Namen oder Ordnern, welche auf einem anderen " "Betriebssystem nicht gültig sind, entfernt werden sollen." -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Beginn des Downloads bei Programmstart" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" msgstr "Mit dem Herunterladen beginnen, sobald ein Laufwerk verfügbar ist" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Gespeicherte Nummer" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Entferne nicht kompatible Zeichen" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Synchronisiere RAW + JPEG Sequenznummern" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" msgstr "" "Unmount (\"Auswerfen\") des Laufwerkes, sobald das Herunterladen beendet ist" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Filme Ordner" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" msgstr "Filme Umbenennen" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" msgstr "Sicherungsordner für Filme:" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." @@ -1985,7 +1751,7 @@ msgstr "" "heruntergeladen wurde, entweder Datei überspringen oder eine eindeutige " "Bezeichnung anfügen." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." @@ -1993,7 +1759,7 @@ msgstr "" "Bitte geben Sie an was geschehen soll, falls bei der Sicherung bereits eine " "Datei mit demselben Namen vorhanden ist, Überspringen oder Überschreiben." -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." @@ -2001,73 +1767,13 @@ msgstr "" "Bilder und Filme können während dem Herunterladen an mehrere Orte gesichert " "werden, z.B. auf externe Laufwerke." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Hinzufügen …" -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Heruntergeladene Dateien nicht mehr anzeigen" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Laufwerk" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "_Fehlerprotokoll" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Datei" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "_Dateiname" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Online Hilfe ..." - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "_Hilfe" - -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Machen Sie eine Spende" - -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Pfad" - -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "_Vorschau" - -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Problemmeldung" - -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Auswahl" - -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "_Grösse" - -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Übersetzung der Applikation" - -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Typ" - -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "_Ansicht" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Importieren Sie Ihre Bilder und Filme schnell und zuverlässig" #, python-format #~ msgid "0 of %s images copied" @@ -2093,9 +1799,17 @@ msgstr "_Ansicht" #~ msgid "Source: %s" #~ msgstr "Quelle: %s" +#~ msgid "Backing up error" +#~ msgstr "Fehler beim Erstellen der Sicherungskopie" + #~ msgid "Backup image already exists" #~ msgstr "Die Sicherungskopie besteht bereits" +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "" +#~ "Ein neuer Tag hat begonnen - die Anzahl der 'Downloads Heute' wird " +#~ "zurückgesetzt" + #~ msgid "Download copying error" #~ msgstr "Fehler beim Kopieren" @@ -2107,10 +1821,16 @@ msgstr "_Ansicht" #~ msgid "%s images skipped" #~ msgstr "%s Bilder übersprungen" +#~ msgid "errors" +#~ msgstr "Fehler" + #, python-format #~ msgid "%s images downloaded" #~ msgstr "%s Bilder heruntergeladen" +#~ msgid "The device can now be safely removed" +#~ msgstr "Das Laufwerk kann nun entfernt werden" + #~ msgid "Backup device missing" #~ msgstr "Das Laufwerk für die Sicherungskopien fehlt" @@ -2133,12 +1853,42 @@ msgstr "_Ansicht" #~ msgid "%(number)s of %(total)s images copied" #~ msgstr "%(number)s von %(total)s Bildern kopiert" +#, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Download von %s abgeschlossen" + +#~ msgid "Warning:" +#~ msgstr "Warnung:" + +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "" +#~ "Einige Voreinstellungen sind ungültig, sie werden auf die Standardwerte " +#~ "zurückgesetzt." + +#~ 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" + +#~ 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." + #~ msgid "Thumbnail cannot be displayed" #~ msgstr "Vorschaubild kann nicht angezeigt werden" #~ msgid "It may be corrupted" #~ msgstr "Es könnte defekt sein" +#~ msgid "No preferences needed to be changed." +#~ msgstr "Es mussten keine Voreinstellungen angepasst werden." + #, python-format #~ msgid "Device scan complete: found %(number)s images on %(device)s" #~ msgstr "" @@ -2190,9 +1940,66 @@ msgstr "_Ansicht" #~ "Ziel: %(destination)s\n" #~ "Fehler: %(errno)s %(strerror)s" +#~ msgid "Problem using pynotify." +#~ msgstr "Bei der Verwendung von pynotify ist ein Problem aufgetreten." + +#~ 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." + +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Die Werte des pynotify Servers konnten nicht abgefragt werden." + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Die %(device)s gefunden auf Pfad %(path)s" + +#~ msgid "No backup devices detected" +#~ msgstr "Es wurden keine Sicherungslaufwerke gefunden" + +#~ msgid "and" +#~ msgstr "und" + +#~ msgid "Using backup device" +#~ msgstr "Das Sicherungslaufwerk wird verwendet" + +#~ msgid "Using backup devices" +#~ msgstr "Die Sicherungslaufwerke werden verwendet" + +#~ msgid "Using manually specified path" +#~ msgstr "Verwende den manuell eingegebenen Pfad" + #~ msgid "_Download " #~ msgstr "_Download " +#~ msgid "_Pause" +#~ msgstr "_Pause" + +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s wird bereits ausgeführt" + +#~ msgid "Using" +#~ msgstr "Verwende" + +#~ msgid "Goodbye" +#~ msgstr "Auf Wiedersehen" + +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Der Download von %s hat begonnen" + +#~ msgid " " +#~ msgstr " " + +#~ msgid "These preferences are not well formed:" +#~ msgstr "Diese Voreinstellungen sind falsch formatiert:" + #~ msgid "Subsecond metadata not present in image" #~ msgstr "Das Bild enthält keine Hunderstelsekunden-Informationen" @@ -2236,9 +2043,15 @@ msgstr "_Ansicht" #~ msgstr "" #~ "<span weight=\"bold\" size=\"x-large\">Umbenennung von Dateien</span>\t" +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "<span weight=\"bold\" size=\"x-large\">Automatisierung</span>" + #~ msgid "Backup photos when downloading" #~ msgstr "Erstelle Sicherung der Bilder beim Herunterladen" +#~ msgid "Automation" +#~ msgstr "Automatisierung" + #~ msgid "Backup folder name:" #~ msgstr "Verzeichnis für Datensicherung:" @@ -2260,12 +2073,44 @@ msgstr "_Ansicht" #~ "Wählen Sie das genaue Verzeichnis für die Bilder, falls die automatische " #~ "Erkennung ausgeschaltet ist." +#~ msgid "Error Log" +#~ msgstr "Fehlerprotokoll" + #~ msgid "Image Rename" #~ msgstr "Dateiumbenennung" #~ msgid "Image Devices" #~ msgstr "Laufwerke mit Bildern" +#~ 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." + #~ msgid "Import your images efficiently and reliably" #~ msgstr "Importieren Sie Ihre Bilder effizient und zuverlässig" @@ -2297,15 +2142,52 @@ msgstr "_Ansicht" #~ msgid "Start downloading upon image device insertion" #~ msgstr "Beginn des Downloads beim Einfügen von Bilderlaufwerken" +#~ msgid "_Report a Problem..." +#~ msgstr "_Problemmeldung" + #~ msgid "_Photos" #~ msgstr "_Fotos" +#~ msgid "_Get Help Online..." +#~ msgstr "_Online Hilfe ..." + #~ msgid "_Thumbnails" #~ msgstr "_Vorschaubilder" +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Die Zeit wird auf Mitternacht zurückgesetzt.\n" + +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Wert wird auf Null zurückgesetzt.\n" + +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "Der Vorgabewert für 'Start des Tages' ist ungültig.\n" + +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Anzahl der ungültigen Downloads von heute.\n" + #~ msgid "No backup device was detected." #~ msgstr "Das Laufwerk für die Sicherungskopien konnte nicht gefunden werden." +#~ 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." + +#~ msgid "Preferences were modified." +#~ msgstr "Die Voreinstellungen wurden geändert." + +#~ msgid "Automatically start download is false" +#~ msgstr "Der automatische Downloadbeginn ist ausgeschaltet" + +#~ msgid "Automatically start download is true" +#~ msgstr "Der automatische Downloadbeginn ist eingeschaltet" + #~ msgid "Preferences were changed." #~ msgstr "Die Voreinstellungen wurden geändert." @@ -2339,6 +2221,16 @@ msgstr "_Ansicht" #~ "Sie können Bilder während des Herunterladens an mehrere Orten sichern, z.B. " #~ "auf externe Festplatten." +#~ msgid "Job Code entered" +#~ msgstr "Auftragsbezeichnung eingegeben" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "" +#~ "Beginne mit den Dowaloads welche auf eine Auftragsbezeichnung gewartet haben" + +#~ msgid "Prompting for Job Code" +#~ msgstr "Frage nach der Auftragsbezeichnung" + #~ msgid "Report an error" #~ msgstr "Fehler anzeigen" @@ -2356,6 +2248,23 @@ msgstr "_Ansicht" #~ "mit demselben Namen bereits existiert." #, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s wurde zum Herunterladen ausgewählt" + +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Abfrage, ob %s zu benutzen ist" + +#~ msgid "Job Code not entered" +#~ msgstr "Keine Auftragsbezeichnung angegeben" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Auftragsbezeichnung wurde schon abgefragt, nicht wieder fragen" + +#~ msgid "Starting downloads" +#~ msgstr "Beginne mit den Downloads" + +#, python-format #~ msgid "" #~ "Image: %(source)s\n" #~ "Error: %(errno)s %(strerror)s" @@ -2370,6 +2279,39 @@ msgstr "_Ansicht" #~ msgid "<b>Image Name Conflicts</b>" #~ msgstr "<b>Konflikte der Bildernamen</b>" +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Der Wert für gespeicherte Anzahl wurde nicht aktualisiert, da gerade ein " +#~ "Download stattfindet" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Der Wert für heutige Downloads wurde nicht aktualisiert, da gerade ein " +#~ "Download stattfindet" + +#, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Quelle: %s\n" + +#~ msgid "Error:" +#~ msgstr "Fehler:" + +#~ msgid "Could not create temporary download directory" +#~ msgstr "Temporäres Download-Verzeichnis konnte nicht erstellt werden" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Ziel: %s" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Fehler: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Das Zielverzeichnis konnte nicht erstellt werden: %(directory)s\n" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2425,6 +2367,16 @@ msgstr "_Ansicht" #~ msgid "Deleted %i images from image device" #~ msgstr "%i Bilder auf dem Laufwerk gelöscht" +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "Von diesem Laufwerk oder dieser Partition wird immer heruntergeladen" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s wurde als Laufwerk zum Herunterladen abgelehnt" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "Von diesem Laufwerk oder dieser Partition wird nie heruntergeladen" + #~ msgid "Enter a new job code, or select a previous one." #~ msgstr "" #~ "Geben Sie eine neue Auftragsbezeichnung an oder wählen Sie eine bereits " @@ -2436,9 +2388,36 @@ msgstr "_Ansicht" #~ msgid "Problem with Image Location Folder" #~ msgstr "Problem mit dem Bildverzeichnis" +#~ msgid "Problem with Download Folder" +#~ msgstr "Problem mit dem Dowanloadverzeichnis" + +#~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Warnung: Der Desktop-Benachrichtigungsdienst ist falsch konfiguriert." + +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Laufwerk %(device)s (%(path)s) ignoriert" + #~ msgid "list image file extensions the program recognizes and exit" #~ msgstr "Anzeigen der gültigen Dateiendungen und beenden" +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "Voreingestellter Wert '%(value)s' ist ungültig" + +#, python-format +#~ msgid "" +#~ "Preference key '%(key)s' is invalid.\n" +#~ "Expected one of %(value)s" +#~ msgstr "" +#~ "Voreingestellter Schlüssel '%(key)s' ist ungültig.\n" +#~ "Erwarteter Wert %(value)s" + +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Copyright Damon Lynch Oktober 2007-2010" + #~ msgid "Delete images from image device upon download completion" #~ msgstr "Bilder auf dem Laufwerk nach erfolgreichem Download löschen" @@ -2466,6 +2445,14 @@ msgstr "_Ansicht" #~ "Sollen Bilder von diesem Laufwerk oder dieser Partition heruntergeladen " #~ "werden?" +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Bitte überprüfen Sie die Voreinstellungen, starten Sie das Programm neu und " +#~ "versuchen es erneut." + #, python-format #~ msgid "" #~ "Sorry, this image location does not exist:\n" @@ -2478,6 +2465,15 @@ msgstr "_Ansicht" #~ "\n" #~ "Erstellen Sie das Verzeichnis oder passen Sie die Voreinstellungen an." +#~ msgid "There is an error in the program preferences." +#~ msgstr "Fehler in den Programmvoreinstellungen." + +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Entschuldigung, diese Voreinstellungen enthalten einen Fehler:\n" + +#~ msgid "Resetting to default values." +#~ msgstr "Die Voreinstellungen werden auf die Standardwerte zurückgesetzt." + #~ msgid "Error in Image Rename preferences" #~ msgstr "Fehler in den Voreinstellungen zum Umbenennen der Dateien" @@ -2489,6 +2485,16 @@ msgstr "_Ansicht" #~ "passen Sie die Voreinstellungen an." #~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "Die Programmvoreinstellungen scheinen gültig zu sein, aber bitte überprüfen " +#~ "Sie diese, um einen problemlosen Programmablauf zu gewährleisten." + +#~ msgid "Some preferences will be reset." +#~ msgstr "Einige Voreinstellungen werden zurückgesetzt." + +#~ msgid "" #~ "Sorry, the Download Folder exists but cannot be written to. Please check the " #~ "folder's permissions, or modify your preferences" #~ msgstr "" @@ -2567,6 +2573,18 @@ msgstr "_Ansicht" #~ "Verzeichnis mit diesem Namen.</i>" #, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "" +#~ "Durchsuchen der Laufwerke abgeschlossen: Keine %(filetypes)s gefunden auf " +#~ "%(device)s" + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Durchsuchen der Laufwerke abgeschlossen: %(number)s %(filetypes)s gefunden " +#~ "auf %(device)s" + +#, python-format #~ msgid "0 of %(number)s %(filetypes)s" #~ msgstr "0 von %(number)s %(filetypes)s" @@ -2577,6 +2595,10 @@ msgstr "_Ansicht" #~ msgid "Photo skipped" #~ msgstr "Bild übersprungen" +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Laufwerk: %s\n" + #~ msgid "Video already exists" #~ msgstr "Der Film exisiert bereits" @@ -2598,6 +2620,9 @@ msgstr "_Ansicht" #~ msgid "photos downloaded" #~ msgstr "Bilder heruntergeladen" +#~ msgid "\n" +#~ msgstr "\n" + #, python-format #~ msgid "The %s(filetype)s was not copied." #~ msgstr "Die %s(filetype)s wurde nicht kopiert." @@ -2622,17 +2647,47 @@ msgstr "_Ansicht" #, python-format #~ msgid "" +#~ "The %(filetype)s subfolder preferences had some unnecessary values removed." +#~ msgstr "" +#~ "Bei den %(filetype)s Unterordner Einstellungen wurden überflüssige Werte " +#~ "entfernt." + +#, python-format +#~ msgid "" #~ "%(filetype)s filename could not be properly generated. Check to ensure there " #~ "is sufficient metadata." #~ msgstr "" #~ "%(filetype)s Dateiname konnte nicht richtig erstellt werden. Bitte " #~ "überprüfen Sie die Vollständigkeit der Metadaten." +#~ msgid "The following download path could not be created:\n" +#~ msgstr "Der folgende Downloadpfad konnte nicht erstellt werden::\n" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + #, python-format #~ msgid "Could not open %s(filetype)s" #~ msgstr "%s(filetype)s konnte nicht geöffnet werden" #, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "%(file_type)s wurde nicht gesichert." + +#, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "Sicherungskopie %(file_type)s wurde überschrieben" + +#, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "%(file_type)s konnte nicht auf %(volume)s gesichert werden" + +#, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Sicherungskopie von %(file_type)s exisiert bereits" + +#, python-format #~ msgid "" #~ "Subfolder: %(subfolder)s\n" #~ "File: %(file)s\n" @@ -2659,15 +2714,118 @@ msgstr "_Ansicht" #~ "Sie die Vollständigkeit der metadaten." #, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "%(file_type)s wurde nicht gesichert" + +#, python-format #~ msgid "%(noFiles)s %(filetypes)s skipped" #~ msgstr "%(noFiles)s %(filetypes)s übersprungen" +#, python-format +#~ msgid "This device has no %(types_searched_for)s to download from." +#~ msgstr "Das Laufwerk enthält keine %(types_searched_for)s zum Herunterladen" + #~ msgid "Photo thumbnail could not be extracted" #~ msgstr "Das Vorschaubild konnte nicht angezeigt werden" +#~ msgid "No backups can occur" +#~ msgstr "Es können keine Sicherungskopien erstellt werden" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Der Pfad %s konnte nicht erstellt werden" + +#~ msgid "Backup path does not exist" +#~ msgstr "Der Pfad zum Sicherungsverzeichnis ist ungültig" + +#~ msgid "A backup location was not found" +#~ msgstr "Es wurde kein Sicherungsverzeichnis gefunden" + +#~ msgid "No suitable backup volume was found" +#~ msgstr "Es wurde kein verwendbares Sicherungslaufwerk gefunden" + +#, python-format +#~ msgid "%(file_type)s could not be backed up" +#~ msgstr "%(file_type)s konnte nicht gesichert werden" + +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Es konnten von dem Laufwerk keine Bilder oder Filme gelöscht werden" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Bild: %(source)s\n" +#~ "Fehler: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "The %(file_type)s Download Folder does not exist.\n" +#~ msgstr "Das %(file_type)s Downloadverzeichnis existiert nicht.\n" + +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "%(number)i %(filetypes)s vom Laufwerk gelöscht" + #~ msgid "No backup device was automatically detected" #~ msgstr "Es wurde kein Sicherungslaufwerk automatisch erkannt" +#, python-format +#~ msgid "" +#~ "Sorry, this device location does not exist:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Please resolve the problem, or modify your preferences." +#~ msgstr "" +#~ "Dieser Laufwerkspfad existiert nicht:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Beheben Sie das Problem oder ändern Sie die Voreinstellungen." + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Bild: %(source)s" + +#~ msgid "Problem with Device Location Folder" +#~ msgstr "Probleme mit dem Laufwerk oder Verzeichnis" + +#, python-format +#~ msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#~ msgstr "" +#~ "Das %(file_type)s Downloadverzeichnis existiert, ist aber schreibgeschützt.\n" + +#~ msgid "" +#~ "Sorry, problems were encountered with your download folders. Please fix the " +#~ "problems or modify the preferences.\n" +#~ "\n" +#~ msgstr "" +#~ "Mit den Downloadverzeichnissen bestehen Probleme. Bitte beheben Sie diese " +#~ "oder passen Sie die Voreinstellungen an.\n" +#~ "\n" + +#, python-format +#~ msgid "Failed to create default video download folder %(folder)s" +#~ msgstr "" +#~ "%(folder)s konnte als Standardverzeichnis zum Herunterladen der Filme nicht " +#~ "erstellt werden" + +#, python-format +#~ msgid "Creating photo download folder %(folder)s" +#~ msgstr "%(folder)s für das Herunterladen der Bilder erstellt" + +#, python-format +#~ msgid "Creating video download folder %(folder)s" +#~ msgstr "%(folder)s für das Herunterladen der Filme erstellt" + +#, python-format +#~ msgid "Failed to create default photo download folder %(folder)s" +#~ msgstr "" +#~ "%(folder)s konnte als Standardverzeichnis zum Herunterladen der Bilder nicht " +#~ "erstellt werden" + +#~ msgid "Problem with Download Folders" +#~ msgstr "Probleme mit den Downloadverzeichnissen" + #~ msgid "image or video number was specified but filename has no number" #~ msgstr "" #~ "Eine Bild- oder Filmnummer wurde angegeben, aber der Dateiname enthält keine " @@ -2691,6 +2849,11 @@ msgstr "_Ansicht" #~ msgid "%s metadata is not present" #~ msgstr "%s Metadaten sind nicht vorhanden" +#~ msgid "Exit program if download completes without any warnings or errors" +#~ msgstr "" +#~ "Programm beenden falls das Herunterladen ohne Fehler oder Warnungen " +#~ "abgeschlossen wird." + #~ msgid "" #~ "Choose whether to skip downloading the file, or to add a unique indentifier." #~ msgstr "" @@ -2720,5 +2883,175 @@ msgstr "_Ansicht" #~ msgid "The %(filetype)s was not copied." #~ msgstr "Die %(filetype)s wurde nicht kopiert." +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Quelle: %(source)s\n" +#~ "Ziel: %(destination)s\n" +#~ "%(problem)s" + +#, python-format +#~ msgid "Attempting to download %s files" +#~ msgstr "Versuche %s Dateien herunterzuladen" + +#~ msgid "Downloading From Cameras" +#~ msgstr "Bilder werden von der Kamera heruntergeladen" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "" +#~ "Das direkte Herunterladen von der Kamera kann unter Umständen schlecht oder " +#~ "gar nicht funktionieren" + +#~ msgid "" +#~ "Downloading from a card reader always works and is generally much faster. It " +#~ "is strongly recommended to use a card reader." +#~ msgstr "" +#~ "Das Herunterladen über einen Kartenleser generell gut und ist normalerweise " +#~ "auch viel schneller. Dies ist die dringend empfohlene Methode." + +#~ msgid "_Show this message again" +#~ msgstr "_Meldung erneut anzeigen" + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Fehler: %(inst)s" + +#~ msgid "Please check your system and try again." +#~ msgstr "Bitte überprüfen Sie Ihr System und versuchen Sie es erneut" + +#~ msgid "Path" +#~ msgstr "Pfad" + +#~ msgid "Date" +#~ msgstr "Datum" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s wurde nicht heruntergeladen" + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s wurde erfolgreich heruntergeladen" + +#~ msgid "File" +#~ msgstr "Datei" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "Type" +#~ msgstr "Typ" + +#~ msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#~ msgstr "" +#~ "Geben Sie eine neue Auftragsbezeichnung ein und drücken Sie EINGABE oder " +#~ "selektieren Sie eine bestehende Auftragsbezeichnung" + +#, python-format +#~ msgid "%(filetype)s was downloaded but there were problems backing up" +#~ msgstr "" +#~ "%(filetype)s wurde heruntergeladen, beim Erstellen der Sicherungskopie " +#~ "traten aber Fehler auf" + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s wurde mit Warnungen heruntergeladen" + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s ist bereit zum Herunterladen" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s wird mit Warnungen weruntergeladen" + +#, python-format +#~ msgid "%(filetype)s is about to be downloaded" +#~ msgstr "%(filetype)s wird weruntergeladen" + +#, python-format +#~ msgid "%(filetype)s was neither downloaded nor backed up" +#~ msgstr "" +#~ "%(filetype)s wurde weder heruntergeladen noch wurde eine Sicherungskopie " +#~ "erstellt" + +#~ msgid "Displaying warning about downloading directly from camera" +#~ msgstr "" +#~ "Eine Warnung betreffend das direkte Herunterladen von der Kamera wird " +#~ "angezeigt" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s kann nicht heruntergeladen werden" + #~ msgid "Preview" #~ msgstr "Vorschau" + +#~ msgid "Backup preferences were changed." +#~ msgstr "Die Benutzervorgaben für Sicherungslaufwerke wurden geändert." + +#~ msgid "_Download All" +#~ msgstr "_Alle Herunterladen" + +#~ msgid "D_ownload Selected" +#~ msgstr "_Herunterladen ausgewählt" + +#~ msgid "_Resume" +#~ msgstr "_Fortsetzen" + +#~ msgid "Subfolder and filename preferences were changed." +#~ msgstr "Die Benutzervorgaben für Unterordner und Dateinamen wurden geändert." + +#~ msgid "Download device settings preferences were changed." +#~ msgstr "Die Benutzervorgaben für Quellaufwerke wurden geändert." + +#~ msgid "Select _All" +#~ msgstr "_Alles auswählen" + +#~ msgid "Select All Vi_deos" +#~ msgstr "Alle Filme auswählen" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Alle Bilder auswählen" + +#~ msgid "Se_lect None" +#~ msgstr "Keine Auswahl" + +#~ msgid "Preview _Folders" +#~ msgstr "Order anzeigen" + +#~ msgid "P_review Columns" +#~ msgstr "Spalten anzeigen" + +#~ msgid "Download folder preferences were changed." +#~ msgstr "Die Benutzervorgaben für Downloadordner wurden geändert." + +#~ msgid "_Device" +#~ msgstr "_Laufwerk" + +#~ msgid "_Filename" +#~ msgstr "_Dateiname" + +#~ msgid "_Path" +#~ msgstr "_Pfad" + +#~ msgid "_Preview" +#~ msgstr "_Vorschau" + +#~ msgid "_Type" +#~ msgstr "_Typ" + +#, python-format +#~ msgid "Warning: backup device %(device)s is currently being downloaded from" +#~ msgstr "" +#~ "Vorsicht: Vom Sicherungslaufwerk %(device)s findet ein Download statt" + +#~ msgid "_Size" +#~ msgstr "_Grösse" + +#, python-format +#~ msgid "%(free)s available" +#~ msgstr "%(free)s verfügbar" @@ -7,241 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-10-22 21:26-0500\n" -"PO-Revision-Date: 2010-11-10 02:21+0000\n" -"Last-Translator: saimon <Unknown>\n" +"POT-Creation-Date: 2011-03-20 18:23-0500\n" +"PO-Revision-Date: 2011-04-01 09:50+0000\n" +"Last-Translator: Daniel Bernal Dotú <Unknown>\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: 2010-12-05 16:48+0000\n" -"X-Generator: Launchpad (build Unknown)\n" +"X-Launchpad-Export-Date: 2011-04-04 05:24+0000\n" +"X-Generator: Launchpad (build 12710)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6353 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:97 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:456 -msgid "New York" -msgstr "Nueva York" - -#: rapid/rapid.py:457 -msgid "Manila" -msgstr "Manila" - -#: rapid/rapid.py:457 -msgid "Prague" -msgstr "Praga" - -#: rapid/rapid.py:457 -msgid "Helsinki" -msgstr "Helsinki" - -#: rapid/rapid.py:457 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:458 -msgid "Tehran" -msgstr "Teherán" - -#: rapid/rapid.py:458 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:458 -msgid "Paris" -msgstr "París" - -#: rapid/rapid.py:458 -msgid "Berlin" -msgstr "Berlín" - -#: rapid/rapid.py:458 -msgid "Sydney" -msgstr "Sídney" - -#: rapid/rapid.py:459 -msgid "Budapest" -msgstr "Budapest" - -#: rapid/rapid.py:459 -msgid "Rome" -msgstr "Roma" - -#: rapid/rapid.py:459 -msgid "Moscow" -msgstr "Moscú" - -#: rapid/rapid.py:459 -msgid "Delhi" -msgstr "Delhi" - -#: rapid/rapid.py:459 -msgid "Warsaw" -msgstr "Varsovia" - -#: rapid/rapid.py:460 -msgid "Jakarta" -msgstr "Jakarta" - -#: rapid/rapid.py:460 -msgid "Madrid" -msgstr "Madrid" - -#: rapid/rapid.py:460 -msgid "Stockholm" -msgstr "Estocolmo" - -#: rapid/rapid.py:493 -msgid "Invalid Downloads Today value.\n" -msgstr "Valor inválido de descargas de hoy.\n" - -#: rapid/rapid.py:494 -msgid "Resetting value to zero.\n" -msgstr "Restableciendo valor a cero.\n" - -#: rapid/rapid.py:533 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "Valor preferencial de 'Inicio del día' corrupto.\n" - -#: rapid/rapid.py:534 -msgid "Resetting to midnight.\n" -msgstr "Restableciendo a medianoche.\n" - -#: rapid/rapid.py:560 -msgid "Error in Photo Rename preferences" -msgstr "Error en las preferencias de renombrado de fotos" - -#: rapid/rapid.py:592 rapid/rapid.py:1714 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Lo siento, pero estas preferencias contienen un error:\n" - -#: rapid/rapid.py:603 -msgid "Resetting to default values." -msgstr "Restableciendo a los valores por defecto." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:678 rapid/renamesubfolderprefs.py:199 -msgid "Job code" -msgstr "Código de trabajo" - -#: rapid/rapid.py:746 -msgid "Error in Video Rename preferences" -msgstr "Error en las preferencias de renombrado de vídeos" - -#: rapid/rapid.py:764 -msgid "Error in Photo Download Subfolders preferences" -msgstr "Error en las preferencias en las subcarpetas de descarga de Fotos" - -#: rapid/rapid.py:781 -msgid "Error in Video Download Subfolders preferences" -msgstr "Error en las preferencias en las subcarpetas de descarga de Videos" - -#: rapid/rapid.py:814 rapid/rapid.py:1545 -msgid "photos and videos" -msgstr "fotos y videos" - -#: rapid/rapid.py:816 rapid/rapid.py:1555 rapid/rapid.py:1683 -msgid "photos" -msgstr "fotos" - -#: rapid/rapid.py:949 -msgid "Select a folder to download photos to" -msgstr "Selecciona un directorio donde descargar las fotos" - -#: rapid/rapid.py:967 -msgid "Select a folder to download videos to" -msgstr "Selecciona un directorio donde descargar los videos" - -#: rapid/rapid.py:1049 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Selecciona un directorio conteniendo %(file_types)s" - -#: rapid/rapid.py:1071 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "" -"Selecciona un directorio a donde hacer una copia de seguridad de " -"%(file_types)s" - -#. 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:1152 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" - -#: rapid/rapid.py:1188 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata 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:1192 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Ejemplo: %s</i>" - -#: rapid/rapid.py:1218 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"El número de descargas de hoy no se actualizó, pues se está haciendo una " -"descarga actualmente." - -#: rapid/rapid.py:1234 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"El número de almacenados no se actualizó, pues se está haciendo una descarga " -"actualmente." - -#: rapid/rapid.py:1264 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" - -#. Preferences list is now empty -#: rapid/rapid.py:1269 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1283 rapid/rapid.py:1557 -msgid "photo" -msgstr "foto" - -#: rapid/rapid.py:1284 rapid/rapid.py:1552 -msgid "video" -msgstr "vídeo" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1521 -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:1523 -msgid "externaldrive2" -msgstr "dispositivoexterno2" - -#: rapid/rapid.py:1547 rapid/rapid.py:1681 -msgid "photos or videos" -msgstr "fotos y vídeos" - -#: rapid/rapid.py:1550 -msgid "videos" -msgstr "vídeos" - -#: rapid/rapid.py:1562 +#: rapid/rapid.py:102 #, python-format msgid "" "%(date)s\n" @@ -250,818 +31,127 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1564 +#: rapid/rapid.py:104 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1567 +#: rapid/rapid.py:107 #, python-format msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1574 +#: rapid/rapid.py:114 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1602 rapid/rapid.py:2278 -msgid "subfolder and filename" -msgstr "subcarpeta y el archivo" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:145 +msgid "Device" +msgstr "Dispositivo" -#: rapid/rapid.py:1604 rapid/rapid.py:2280 -msgid "filename" -msgstr "nombre de archivo" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:159 +msgid "Size" +msgstr "Tamaño" -#: rapid/rapid.py:1606 rapid/rapid.py:2282 -msgid "subfolder" -msgstr "subcarpeta" +#: rapid/rapid.py:162 +msgid "Download Progress" +msgstr "Progreso de descarga" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1697 +#: rapid/rapid.py:938 msgid "scanning..." msgstr "explorando..." -#: rapid/rapid.py:1812 -msgid "The following download path could not be created:\n" -msgstr "" - -#: rapid/rapid.py:1813 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1814 rapid/rapid.py:1815 rapid/rapid.py:1830 -#: rapid/rapid.py:1831 rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Download cannot proceed" -msgstr "No se puede proceder con la descarga" - -#: rapid/rapid.py:1828 rapid/rapid.py:4999 -msgid "There is an error in the program preferences." -msgstr "Hay un error en las preferencis del programa." - -#: rapid/rapid.py:1829 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Por favor, revise las preferencias, reinicie el programa e intente de nuevo." - -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2006 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2017 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Escaneo del dispositivo completo: se encontro %(number)s %(filetypes)s en " -"%(device)s" - -#: rapid/rapid.py:2024 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "" -"Escaneo del dispositivo completo: no se encuentran %(filetypes)s en " -"%(device)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:2045 -msgid "The device can now be safely removed" -msgstr "El dispositivo ya se puede extraer de forma segura" - -#: rapid/rapid.py:2051 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s descargados" - -#: rapid/rapid.py:2054 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "" - -#: rapid/rapid.py:2057 rapid/rapid.py:5792 -msgid "warnings" -msgstr "avisos" - -#: rapid/rapid.py:2059 rapid/rapid.py:5796 -msgid "errors" -msgstr "errores" - -#: rapid/rapid.py:2089 -#, python-format -msgid "Source: %s\n" -msgstr "Origen: %s\n" - -#: rapid/rapid.py:2091 -#, python-format -msgid "Device: %s\n" -msgstr "Dispositivo: %s\n" - -#: rapid/rapid.py:2092 -#, python-format -msgid "Destination: %s" -msgstr "Destino: %s" - -#: rapid/rapid.py:2093 rapid/rapid.py:2096 -msgid "Could not create temporary download directory" -msgstr "No se pudo crear el directorio de descarga temporal" - -#: rapid/rapid.py:2096 -msgid "Error:" -msgstr "Error:" - -#: rapid/rapid.py:2120 -msgid "Backup path does not exist" -msgstr "" - -#: rapid/rapid.py:2121 -#, python-format -msgid "The path %s could not be created" -msgstr "" - -#: rapid/rapid.py:2122 -msgid "No backups can occur" -msgstr "" - -#: rapid/rapid.py:2151 -#, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" -msgstr "" -"Origen: %(source)s\n" -"Destino: %(destination)s\n" -"%(problem)s" - -#: rapid/rapid.py:2182 rapid/rapid.py:2528 rapid/rapid.py:2563 -#: rapid/rapid.py:2591 rapid/rapid.py:2622 rapid/rapid.py:2641 -#, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" -msgstr "" -"Origen: %(source)s\n" -"Destino: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2197 -msgid "Please check your system and try again." -msgstr "" - -#: rapid/rapid.py:2217 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" - -#: rapid/rapid.py:2257 -msgid "Photo has already been downloaded" -msgstr "" - -#: rapid/rapid.py:2258 rapid/rapid.py:2657 -#, python-format -msgid "Source: %(source)s" -msgstr "Origen: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2456 -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:2527 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "" - -#: rapid/rapid.py:2531 -#, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "" - -#: rapid/rapid.py:2535 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "" - -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "" - -#: rapid/rapid.py:2560 rapid/rapid.py:2588 rapid/rapid.py:2621 -#: rapid/rapid.py:2640 -msgid "Backing up error" -msgstr "Error en copia de seguridad" - -#: rapid/rapid.py:2561 rapid/rapid.py:2589 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "El directorio de destino no puede ser creado: %(directory)s\n" - -#: rapid/rapid.py:2565 rapid/rapid.py:2624 -#, python-format -msgid "Error: %(inst)s" -msgstr "Error: %(inst)s" - -#: rapid/rapid.py:2566 rapid/rapid.py:2594 rapid/rapid.py:2625 -#: rapid/rapid.py:2644 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "" - -#: rapid/rapid.py:2593 rapid/rapid.py:2643 -#, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Error: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2656 -#, python-format -msgid "%(file_type)s could not be backed up" -msgstr "" - -#: rapid/rapid.py:2659 -msgid "No suitable backup volume was found" -msgstr "" - -#: rapid/rapid.py:2661 -msgid "A backup location was not found" -msgstr "" - -#: rapid/rapid.py:2715 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." -msgstr "" +#: rapid/rapid.py:1639 +msgid "Download" +msgstr "Descargar" -#: rapid/rapid.py:2788 -#, python-format -msgid "Download has started from %s" -msgstr "La descarga empezó desde %s" - -#: rapid/rapid.py:2799 -#, python-format -msgid "Attempting to download %s files" -msgstr "" +#: rapid/rapid.py:1642 +msgid "Pause" +msgstr "Pausar" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2831 rapid/rapid.py:2898 +#. ~ scan_pid = rpd_file.scan_pid +#. ~ unique_id = rpd_file.unique_id +#: rapid/rapid.py:1906 #, python-format msgid "%(number)s of %(total)s %(filetypes)s" msgstr "%(number)s de %(total)s %(filetypes)s" -#: rapid/rapid.py:2894 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" -msgstr "%(number)s de %(total)s %(filetypes)s (%(remaining)s restantes)" - -#: rapid/rapid.py:2919 rapid/rapid.py:2923 -msgid "Could not delete photo or video from device" -msgstr "No se pudo borrar foto o video del dispositivo" - -#: rapid/rapid.py:2920 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" -msgstr "" -"Foto: %(source)s\n" -"Error: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2924 -#, python-format -msgid "Photo: %(source)s" -msgstr "Foto: %(source)s" - -#: rapid/rapid.py:2926 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "" - -#: rapid/rapid.py:2939 -#, 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:3054 rapid/rapid.py:3523 -msgid "Device" -msgstr "Dispositivo" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3059 rapid/rapid.py:3512 -msgid "Size" -msgstr "Tamaño" - -#: rapid/rapid.py:3062 -msgid "Download Progress" -msgstr "Progreso de descarga" - -#: rapid/rapid.py:3150 -msgid "Downloading From Cameras" -msgstr "Descargando desde las camaras" - -#: rapid/rapid.py:3156 -msgid "Downloading directly from a camera may work poorly or not at all" -msgstr "" -"Descargas directas desde una cámara puede que no funcionen o funcionen mal" - -#: rapid/rapid.py:3157 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." -msgstr "" - -#: rapid/rapid.py:3171 -msgid "_Show this message again" -msgstr "_Mostrar este mensaje de nuevo" - -#: rapid/rapid.py:3206 -msgid "Device Detected" -msgstr "Dispositivo detectado" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3215 -msgid "" -"Should this device or partition be used to download photos or videos from?" -msgstr "" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "_Remember this choice" -msgstr "_Recordar esta elección" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3271 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s seleccionado para descargar de" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3274 -msgid "This device or partition will always be used to download from" -msgstr "Siempre se descargará de este dispositivo o partición" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3277 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s rechazado como dispositivo de descarga" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3280 -msgid "This device or partition will never be used to download from" -msgstr "Jamás se descargará de este dispositivo o partición" - -#: rapid/rapid.py:3287 -msgid "Remove all Job Codes?" -msgstr "¿Borrar todos los Códigos de Trabajo?" - -#: rapid/rapid.py:3304 -msgid "Should all Job Codes be removed?" -msgstr "¿Deberían ser removidos todos los Codigos de Trabajo?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3332 -msgid "Enter a Job Code" -msgstr "Ingrese un Código de trabajo" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a new Job Code, or select a previous one" -msgstr "Inserte un nuevo código de trabajo o seleccione uno anterior" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3354 -msgid "Enter a new Job Code" -msgstr "" - -#: rapid/rapid.py:3359 rapid/rapid.py:4534 -msgid "Job Code:" -msgstr "Código de trabajo:" - -#: rapid/rapid.py:3406 -msgid "Job Code entered" -msgstr "Código de trabajo ingresado" - -#: rapid/rapid.py:3408 -msgid "Job Code not entered" -msgstr "Código de trabajo no introducido" - -#: rapid/rapid.py:3458 -msgid "Status" -msgstr "Estado" - -#: rapid/rapid.py:3466 -msgid "Type" -msgstr "Tipo" - -#: rapid/rapid.py:3475 rapid/rapid.py:4961 rapid/rapid.py:4963 -msgid "Photo" -msgstr "Foto" - -#: rapid/rapid.py:3477 -msgid "File" -msgstr "Archivo" - -#: rapid/rapid.py:3492 -msgid "Job Code" -msgstr "" - -#: rapid/rapid.py:3502 -msgid "Date" -msgstr "Fecha" - -#: rapid/rapid.py:3534 rapid/renamesubfolderprefs.py:195 -msgid "Filename" -msgstr "Nombre de archivo" - -#: rapid/rapid.py:3545 -msgid "Path" -msgstr "Ruta" - -#: rapid/rapid.py:3955 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "" - -#: rapid/rapid.py:3957 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "" - -#: rapid/rapid.py:3959 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "" - -#: rapid/rapid.py:3961 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" -msgstr "" - -#: rapid/rapid.py:3963 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "" +#: rapid/rapid.py:2239 rapid/preferencesdialog.py:817 rapid/rpdfile.py:118 +msgid "photos" +msgstr "fotos" -#: rapid/rapid.py:3965 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "" +#: rapid/rapid.py:2241 rapid/rpdfile.py:113 +msgid "videos" +msgstr "vídeos" -#: rapid/rapid.py:3967 -#, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "" +#: rapid/rapid.py:2244 +msgid "Free space:" +msgstr "Espacio libre:" -#: rapid/rapid.py:3969 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2256 #, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "" +msgid "(%(file_type)s)" +msgstr "(%(file_type)s)" -#: rapid/rapid.py:3971 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2260 #, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "" +msgid "%(free)s %(file_type)s" +msgstr "%(free)s %(file_type)s" -#: rapid/rapid.py:4341 -msgid "Preview" -msgstr "Vista previa" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2265 +msgid "; " +msgstr "; " -#: rapid/rapid.py:4556 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2270 +msgid "." +msgstr "." -#: rapid/rapid.py:4928 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2276 #, python-format -msgid "%(free)s available" -msgstr "" +msgid "%(free)s free" +msgstr "%(free)s libre" #. user manually specified backup location -#: rapid/rapid.py:4934 +#: rapid/rapid.py:2282 #, python-format msgid "Backing up to %(path)s" -msgstr "" +msgstr "Guardar en %(path)s" -#: rapid/rapid.py:4939 +#: rapid/rapid.py:2287 #, python-format msgid "%(freespace)s. %(backuppaths)s." -msgstr "" - -#: rapid/rapid.py:4948 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" - -#: rapid/rapid.py:4952 -msgid "Problem with Device Location Folder" -msgstr "" - -#: rapid/rapid.py:4961 -msgid "Video" -msgstr "Video" - -#: rapid/rapid.py:4968 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "" - -#: rapid/rapid.py:4977 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "" - -#: rapid/rapid.py:4982 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" - -#: rapid/rapid.py:4985 -msgid "Problem with Download Folder" -msgstr "Problema con la Carpeta de Descarga" - -#: rapid/rapid.py:4987 -msgid "Problem with Download Folders" -msgstr "" - -#: rapid/rapid.py:5000 -msgid "Some preferences will be reset." -msgstr "Algunas preferencias serán restablecidas." - -#: rapid/rapid.py:5033 -msgid "Displaying warning about downloading directly from camera" -msgstr "" - -#: rapid/rapid.py:5043 -#, python-format -msgid "Prompting whether to use %s" -msgstr "Preguntando si usar o no %s" - -#: rapid/rapid.py:5070 -msgid "Prompting for Job Code" -msgstr "Pidiendo un Código de trabajo" - -#: rapid/rapid.py:5074 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Preguntando por código de trabajo, no volver a preguntar" - -#: rapid/rapid.py:5091 -msgid "Starting downloads" -msgstr "Iniciando descargas" - -#. autostart is true -#: rapid/rapid.py:5095 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "Iniciando descargas que han sido esperadas por un Código de trabajo" - -#: rapid/rapid.py:5142 -#, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5147 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5151 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5156 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "" - -#: rapid/rapid.py:5181 -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:5183 -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:5185 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "Lo siento, algunas preferencias son invalidas y serán restablecidas" - -#: rapid/rapid.py:5186 -msgid "Warning:" -msgstr "Aviso:" +msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:5191 -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:5198 -msgid "Preferences were modified." -msgstr "Las preferencias fueron modificadas." - -#: rapid/rapid.py:5199 -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:5203 -msgid "No preferences needed to be changed." -msgstr "Ninguna preferencia necesita ser cambiada." - -#: rapid/rapid.py:5205 -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:5215 -msgid "Problem using pynotify." -msgstr "Problema usando pynotify." - -#: rapid/rapid.py:5231 -msgid "Failed to receive pynotify server capabilities." -msgstr "Fallo al recibir capacidades del servidor pynotify" - -#: rapid/rapid.py:5242 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Advertencia: el servidor de notificaciones del entorno de escritorio no está " -"configurado correctamente." - -#: rapid/rapid.py:5290 -msgid "and" -msgstr "y" - -#: rapid/rapid.py:5295 -msgid "Using backup devices" -msgstr "Usando dispositivo de copia de seguridad" - -#: rapid/rapid.py:5297 -msgid "Using backup device" -msgstr "Usando dispositivo de copia de seguridad" - -#: rapid/rapid.py:5299 -msgid "No backup devices detected" -msgstr "Dispositivos de copia de seguridad no detectados" - -#: rapid/rapid.py:5349 rapid/rapid.py:5511 -#, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Dispositivo %(device)s (%(path)s) ignorado" - -#: rapid/rapid.py:5470 -#, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Detectado %(device)s con ruta %(path)s" - -#: rapid/rapid.py:5474 -msgid "Automatically start download is true" -msgstr "Iniciar automaticamente la descarga está activa" - -#: rapid/rapid.py:5476 -msgid "Automatically start download is false" -msgstr "Iniciar automaticamente la descarga está desactivada" - -#: rapid/rapid.py:5529 -msgid "Using manually specified path" -msgstr "Usando manualmente la ruta especifica" - -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5597 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" -msgstr "" - -#: rapid/rapid.py:5613 -msgid "D_ownload Selected" -msgstr "" - -#: rapid/rapid.py:5713 rapid/rapid.py:5764 -msgid "All downloads complete" -msgstr "Todas las descargas completadas" - -#: rapid/rapid.py:5728 -msgid "MB/s" -msgstr "MB/s" - -#: rapid/rapid.py:5738 -msgid "About 1 second remaining" -msgstr "Aproximadamente 1 segundo restante" - -#: rapid/rapid.py:5740 -#, python-format -msgid "About %i seconds remaining" -msgstr "Aproximadamente %i segundos restantes" - -#: rapid/rapid.py:5742 -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:5747 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Resta cerca de %(minutes)i:%(seconds)02i minutos" - -#: rapid/rapid.py:5767 rapid/rapid.py:5773 rapid/rapid.py:5779 -#: rapid/rapid.py:5785 rapid/rapid.py:5790 rapid/rapid.py:5794 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" - -#: rapid/rapid.py:5769 rapid/rapid.py:5781 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s descargados" - -#: rapid/rapid.py:5775 rapid/rapid.py:5787 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "" - -#: rapid/rapid.py:5955 -msgid "_Resume" -msgstr "_Reanudar" - -#: rapid/rapid.py:5958 -msgid "_Download All" -msgstr "_Descargar tod" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:5967 -msgid "_Pause" -msgstr "_Pausar" - -#: rapid/rapid.py:6079 -msgid "Download device settings preferences were changed." -msgstr "" - -#: rapid/rapid.py:6091 -msgid "Backup preferences were changed." -msgstr "" - -#: rapid/rapid.py:6097 -msgid "Subfolder and filename preferences were changed." -msgstr "" - -#: rapid/rapid.py:6108 -msgid "Download folder preferences were changed." -msgstr "" - -#: rapid/rapid.py:6307 -msgid "Goodbye" -msgstr "Adiós" +#: rapid/rapid.py:2470 +msgid "Thumbnails" +msgstr "Miniaturas" #. 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:6318 +#: rapid/rapid.py:2511 #, python-format msgid "" "display program information on the command line as the program runs " @@ -1070,577 +160,1168 @@ 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:6319 +#: rapid/rapid.py:2512 msgid "display debugging information when run from the command line" msgstr "" +"mostrar información de depuración cuando se ejecute desde la línea de " +"comandos" -#: rapid/rapid.py:6320 +#: rapid/rapid.py:2513 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:6322 +#: rapid/rapid.py:2515 msgid "list photo and video file extensions the program recognizes and exit" msgstr "" +"listar las extensiones de archivo para fotos y vídeos que el programa " +"reconoce y salir" -#: rapid/rapid.py:6323 +#: rapid/rapid.py:2516 msgid "reset all program settings and preferences and exit" msgstr "" -#: rapid/rapid.py:6337 +#: rapid/rapid.py:2529 msgid "Photos:" msgstr "Fotos:" -#: rapid/rapid.py:6337 +#: rapid/rapid.py:2529 msgid "Videos:" msgstr "Videos:" -#: rapid/rapid.py:6342 +#: rapid/rapid.py:2534 #, python-format msgid "and %s" msgstr "y %s" -#: rapid/rapid.py:6350 +#: rapid/rapid.py:2542 msgid "All settings and preferences have been reset" msgstr "" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6354 rapid/rapid.py:6355 rapid/rapid.py:6357 -#: rapid/rapid.py:6362 rapid/rapid.py:6366 -msgid "Using" -msgstr "Usando" +#: rapid/rapid.py:2551 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." +msgstr "" + +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Dispositivo detectado" -#: rapid/rapid.py:6359 -msgid "\n" -msgstr "\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "" -#. this application is already running -#: rapid/rapid.py:6383 -#, python-format -msgid "%s is already running" -msgstr "%s ya se está ejecutando" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "_Recordar esta elección" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Fecha" -#: rapid/renamesubfolderprefs.py:194 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Texto" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Nombre de archivo" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Metadatos" -#: rapid/renamesubfolderprefs.py:197 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Secuencias" -#: rapid/renamesubfolderprefs.py:200 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:545 +msgid "Job code" +msgstr "Código de trabajo" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Fecha de la imagen" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:151 msgid "Video date" msgstr "" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Hoy" -#: rapid/renamesubfolderprefs.py:203 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Ayer" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:205 +#: rapid/generatenameconfig.py:155 msgid "Download time" msgstr "" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:207 +#: rapid/generatenameconfig.py:157 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:209 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Nombre" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:211 +#: rapid/generatenameconfig.py:161 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:213 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Número de imagen" -#: rapid/renamesubfolderprefs.py:214 +#: rapid/generatenameconfig.py:164 msgid "Video number" msgstr "" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:216 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Apertura" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:218 +#: rapid/generatenameconfig.py:168 msgid "ISO" msgstr "ISO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:220 +#: rapid/generatenameconfig.py:170 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:222 +#: rapid/generatenameconfig.py:172 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:224 +#: rapid/generatenameconfig.py:174 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:226 +#: rapid/generatenameconfig.py:176 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:228 +#: rapid/generatenameconfig.py:178 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:230 +#: rapid/generatenameconfig.py:180 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:232 +#: rapid/generatenameconfig.py:182 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:234 +#: rapid/generatenameconfig.py:184 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:236 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Nombre propietario" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Códec" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Ancho" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Alto" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Duración" -#: rapid/renamesubfolderprefs.py:241 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Cuadros por Segundo" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:243 +#: rapid/generatenameconfig.py:193 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:245 +#: rapid/generatenameconfig.py:195 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:247 +#: rapid/generatenameconfig.py:197 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:249 +#: rapid/generatenameconfig.py:199 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:251 +#: rapid/generatenameconfig.py:201 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:253 +#: rapid/generatenameconfig.py:203 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:255 +#: rapid/generatenameconfig.py:205 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:257 +#: rapid/generatenameconfig.py:207 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:259 +#: rapid/generatenameconfig.py:209 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:261 +#: rapid/generatenameconfig.py:211 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:263 +#: rapid/generatenameconfig.py:213 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:265 +#: rapid/generatenameconfig.py:215 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:267 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "minúsculas" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Un dígito" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Dos dígitos" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Tres dígitos" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Cuatro dígitos" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Cinco dígitos" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Seis dígitos" -#: rapid/renamesubfolderprefs.py:274 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "Siete digitos" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:276 +#: rapid/generatenameconfig.py:226 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:278 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "AAAAMMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:280 +#: rapid/generatenameconfig.py:230 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:282 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "AAMMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:284 +#: rapid/generatenameconfig.py:234 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:286 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "MMDDAAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:288 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "MMDDAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:290 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "MMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:292 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "DDMMAAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:294 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "DDMMAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:296 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "AAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:298 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "AA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:300 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:302 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "DD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:304 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "HHMMSS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:306 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "HHMM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:308 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "HH-MM-SS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:310 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "HH-MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:312 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "HH" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:314 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "MM (minutos)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:316 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "SS" -#: rapid/renamesubfolderprefs.py:801 +#: rapid/preferencesdialog.py:364 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Preferencias de subcarpeta no debería empezar con una %s" + +#: rapid/preferencesdialog.py:366 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Preferencias de subcarpeta no debería terminar con una %s" + +#: rapid/preferencesdialog.py:370 +#, 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/preferencesdialog.py:384 rapid/preferencesdialog.py:668 +msgid "Remove all Job Codes?" +msgstr "¿Borrar todos los Códigos de Trabajo?" + +#: rapid/preferencesdialog.py:401 rapid/preferencesdialog.py:685 +msgid "Should all Job Codes be removed?" +msgstr "¿Deberían ser removidos todos los Codigos de Trabajo?" + +#: rapid/preferencesdialog.py:431 +msgid "Error in Photo Rename preferences" +msgstr "Error en las preferencias de renombrado de fotos" + +#: rapid/preferencesdialog.py:613 +msgid "Error in Video Rename preferences" +msgstr "Error en las preferencias de renombrado de vídeos" + +#: rapid/preferencesdialog.py:634 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Error en las preferencias en las subcarpetas de descarga de Fotos" + +#: rapid/preferencesdialog.py:651 +msgid "Error in Video Download Subfolders preferences" +msgstr "Error en las preferencias en las subcarpetas de descarga de Videos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:710 +msgid "Enter a Job Code" +msgstr "Ingrese un Código de trabajo" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:727 +msgid "Enter a new Job Code, or select a previous one" +msgstr "Inserte un nuevo código de trabajo o seleccione uno anterior" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:730 +msgid "Enter a new Job Code" +msgstr "" + +#: rapid/preferencesdialog.py:735 +msgid "Job Code:" +msgstr "Código de trabajo:" + +#: rapid/preferencesdialog.py:815 rapid/rpdfile.py:108 +msgid "photos and videos" +msgstr "fotos y videos" + +#: rapid/preferencesdialog.py:964 +msgid "Select a folder to download photos to" +msgstr "Selecciona un directorio donde descargar las fotos" + +#: rapid/preferencesdialog.py:982 +msgid "Select a folder to download videos to" +msgstr "Selecciona un directorio donde descargar los videos" + +#: rapid/preferencesdialog.py:1064 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Selecciona un directorio conteniendo %(file_types)s" + +#: rapid/preferencesdialog.py:1086 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "" +"Selecciona un directorio a donde hacer una copia de seguridad de " +"%(file_types)s" + +#. 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/preferencesdialog.py:1172 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" +msgstr "" + +#: rapid/preferencesdialog.py:1211 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata 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/preferencesdialog.py:1215 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Ejemplo: %s</i>" + +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1291 +#, python-format +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." +msgstr "" + +#. check subfolder preferences for bad values +#: rapid/preferencesdialog.py:1305 rapid/rpdfile.py:120 rapid/rpdfile.py:241 +msgid "photo" +msgstr "foto" + +#: rapid/preferencesdialog.py:1306 rapid/rpdfile.py:115 rapid/rpdfile.py:267 +msgid "video" +msgstr "vídeo" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1566 +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/preferencesdialog.py:1568 +msgid "externaldrive2" +msgstr "dispositivoexterno2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "Nueva York" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manila" + +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Praga" + +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinki" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Teherán" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "París" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlín" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sídney" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Budapest" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Roma" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moscú" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Delhi" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Varsovia" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jakarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madrid" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Estocolmo" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:181 +msgid "subfolder" +msgstr "subcarpeta" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:179 +msgid "filename" +msgstr "nombre de archivo" + +#: rapid/problemnotification.py:80 +#, python-format +msgid "Date time value %s appears invalid." +msgstr "" + +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "" + +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "" + +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." +msgstr "" + +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" +msgstr "" + +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" +msgstr "" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "" + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "" + +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." +msgstr "" + +#: rapid/problemnotification.py:102 #, python-format msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." msgstr "" -"Clave preferida '%(key)s' es inválida.\n" -"Esperado uno de %(value)s" -#: rapid/renamesubfolderprefs.py:808 +#: rapid/problemnotification.py:103 #, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "Valor '%(value)s' es inválido" +msgid "%(filetype)s was already downloaded" +msgstr "" -#: rapid/renamesubfolderprefs.py:812 -msgid "These preferences are not well formed:" -msgstr "Estas preferencias no están bien formadas:" +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." +msgstr "" -#: rapid/renamesubfolderprefs.py:1525 +#: rapid/problemnotification.py:108 #, python-format -msgid "Subfolder preferences should not start with a %s" -msgstr "Preferencias de subcarpeta no debería empezar con una %s" +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "" -#: rapid/renamesubfolderprefs.py:1527 +#: rapid/problemnotification.py:109 #, python-format -msgid "Subfolder preferences should not end with a %s" -msgstr "Preferencias de subcarpeta no debería terminar con una %s" +msgid "There is no data with which to name the %(filetype)s." +msgstr "" -#: rapid/renamesubfolderprefs.py:1531 +#: rapid/problemnotification.py:111 #, python-format -msgid "Subfolder preferences should not contain two %s one after the other" +msgid "Error: %(errorno)s %(strerror)s" +msgstr "" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "" + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "" + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr "" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr "" + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "" + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "" + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "" + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "" + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "" + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "" + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "" + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "" + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "" + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "" + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "" + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "" + +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr "" + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr "" + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "" + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "" + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "" + +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "" + +#: rapid/problemnotification.py:403 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "" +"Fotos detectadas con el mismo nombre de archivo, pero tomadas en momentos " +"diferentes" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "" + +#: rapid/rpdfile.py:110 +msgid "photos or videos" +msgstr "fotos y vídeos" + +#: rapid/rpdfile.py:134 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/rpdfile.py:242 +msgid "Photo" +msgstr "Foto" + +#: rapid/rpdfile.py:268 +msgid "Video" +msgstr "Video" + +#: rapid/subfolderfile.py:177 +msgid "subfolder and filename" +msgstr "subcarpeta y el archivo" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "Acerca de..." + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Descargar / Pausar" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "Obtener Ayuda en Línea..." + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "Hacer una Donación..." + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "Informar de un problema..." + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "Traducir esta aplicación..." + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Limpiar descargas completadas" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" +msgstr "" + +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "_Registro de errores" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Archivo" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "Ay_uda" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Hacer una donación" + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Seleccionar" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Traducir esta aplicación..." + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" msgstr "" -"Preferencias de subcarpeta no debería contener dos %s uno después que el otro" -#: rapid/glade3/rapid.glade.h:1 +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "_Ver" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " hh:mm" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "<b>Respaldo</b>" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Compatibilidad con otros Sistemas Operativos</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "<b>Dispositivos</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Carpeta de descargas</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Subcarpeta de descargas</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Ejemplo</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Códigos de trabajo</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Automatización de programa</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Números de secuencia</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/media/externaldrive/Imágenes</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Ejemplo: /home/user/Pictures</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Ejemplo:</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Nuevo:</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 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 +#: rapid/glade3/prefs.ui.h:20 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 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Dispositivos</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 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 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Códigos de trabajo</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.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:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Agregar identificador único" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Detectar automáticamente dispositivos de almacenamiento portables" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Detectar automáticamente dispositivos de respaldo" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Detectar dispositivos automaticamente" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Automatización" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Respaldo" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Ruta de respaldo:" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1649,29 +1330,25 @@ msgstr "" "serán creadas automáticamente en la carpeta usando la estructura " "especificada abajo." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." msgstr "" -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Copyright Damon Lynch 2007-10" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Día de inicio:" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Dispositivos" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1684,42 +1361,38 @@ msgid "" "reader.</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Descargar / Pausar" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Carpeta de descarga:" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Descargas de hoy:" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Manejo de errores" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Registro de error" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" +msgstr "" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" -msgstr "Salir del programa si se completa la descarga sin avisos ni errores" +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" +msgstr "" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 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:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." msgstr "" -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1729,123 +1402,62 @@ msgstr "" "portátil, será revisado completamente en busca de imágenes. En dispositivos " "grandes, esto puede tomar algún tiempo." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "Importe sus fotos y vídeos de forma eficaz y fiable" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Códigos de trabajo" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Ubicación:" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Sobreescribir" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Preferencias: Rapid Photo Downloader" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "R_emover todo" -#: rapid/glade3/rapid.glade.h:72 -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:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Opciones de renombre" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Seleccionar todas las fo_tos" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Seleccionar todos los ví_deos" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "Seleccionar _todo" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Saltar" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Saltar descarga" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " -"install the <i>kaa metadata</i> package for python." +"install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " +"python." msgstr "" -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1854,7 +1466,7 @@ msgid "" "a folder in it with one of these names.</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1862,137 +1474,130 @@ 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:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." msgstr "" -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Empezar descargas al iniciar el programa" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" msgstr "" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Número almacenado:" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Quitar carácteres incompatibles" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Sincronizar números de secuencia de RAW + JPEG" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" msgstr "" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Carpetas de vídeo" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" msgstr "Renombrar vídeo" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" msgstr "" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." msgstr "" -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." msgstr "" -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." msgstr "" -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Añadir…" -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Limpiar descargas completadas" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Dispositivo" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "_Registro de errores" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Archivo" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "Nombre de _archivo" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Conseguir ayuda online" - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "Ay_uda" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Importe sus fotos y vídeos de forma eficaz y fiable" -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Hacer una donación" +#, python-format +#~ msgid "0 of %s images copied" +#~ msgstr "0 de %s imagenes copiadas" -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "" +#~ msgid "warnings" +#~ msgstr "avisos" -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "Vista _previa" +#~ msgid "errors" +#~ msgstr "errores" -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Reportar problema..." +#~ msgid "MB/s" +#~ msgstr "MB/s" -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Seleccionar" +#~ msgid "and" +#~ msgstr "y" -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "_Tamaño" +#~ msgid "_Pause" +#~ msgstr "_Pausar" -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Traducir esta aplicación..." +#~ msgid "Goodbye" +#~ msgstr "Adiós" -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Tipo" +#~ msgid " " +#~ msgstr " " -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "_Ver" +#~ 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." -#, python-format -#~ msgid "0 of %s images copied" -#~ msgstr "0 de %s imagenes copiadas" +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Lo siento, pero estas preferencias contienen un error:\n" #~ msgid "Select an image folder" #~ msgstr "Seleccionar una carpeta de imágenes" @@ -2020,12 +1625,22 @@ msgstr "_Ver" #~ msgstr "La imagen ya existe" #, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Descarga completa desde %s" + +#~ msgid "Problem using pynotify." +#~ msgstr "Problema usando pynotify." + +#, python-format #~ msgid "Source: %s" #~ msgstr "Origen: %s" #~ msgid "_Photos" #~ msgstr "_Fotos" +#~ msgid "_Get Help Online..." +#~ msgstr "_Conseguir ayuda online" + #~ msgid "_Thumbnails" #~ msgstr "_Miniaturas" @@ -2055,15 +1670,43 @@ msgstr "_Ver" #~ "Destino: %(destination)s\n" #~ "Error: %(errno)s %(strerror)s" +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "Lo siento, algunas preferencias son invalidas y serán restablecidas" + #~ msgid "Image skipped" #~ msgstr "Imagen saltada" +#~ msgid "No backup devices detected" +#~ msgstr "Dispositivos de copia de seguridad no detectados" + +#~ msgid "Using backup device" +#~ msgstr "Usando dispositivo de copia de seguridad" + +#~ msgid "Using backup devices" +#~ msgstr "Usando dispositivo de copia de seguridad" + +#, python-format +#~ msgid "About %i seconds remaining" +#~ msgstr "Aproximadamente %i segundos restantes" + +#~ msgid "About 1 minute remaining" +#~ msgstr "Aproximadamente 1 minuto restante" + +#~ msgid "About 1 second remaining" +#~ msgstr "Aproximadamente 1 segundo restante" + #~ msgid "_Download " #~ msgstr "_Descargar " #~ msgid "images downloaded" #~ msgstr "imagenes descargadas" +#~ msgid "All downloads complete" +#~ msgstr "Todas las descargas completadas" + +#~ msgid "Using" +#~ msgstr "Usando" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2093,6 +1736,14 @@ msgstr "_Ver" #~ "Problema: %(problem)s" #, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s" +#~ msgstr "" +#~ "Origen: %(source)s\n" +#~ "Destino: %(destination)s" + +#, python-format #~ msgid "%s images skipped" #~ msgstr "%s imagenes saltadas" @@ -2106,6 +1757,9 @@ msgstr "_Ver" #~ "%(directory)s\n" #~ "Error: %(errno)s %(strerror)s" +#~ msgid "The device can now be safely removed" +#~ msgstr "El dispositivo ya se puede extraer de forma segura" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2116,6 +1770,9 @@ msgstr "_Ver" #~ "Destino: %(destination)s\n" #~ "Error: %(errorno)s %(strerror)s" +#~ msgid "Preferences were modified." +#~ msgstr "Las preferencias fueron modificadas." + #, python-format #~ msgid "%(number)s of %(total)s images copied" #~ msgstr "%(number)s de %(total)s imágenes copiadas" @@ -2123,6 +1780,9 @@ msgstr "_Ver" #~ msgid "Error in Image Rename preferences" #~ msgstr "Error en las preferencias de Renombrar Imagen" +#~ msgid "Download cannot proceed" +#~ msgstr "No se puede proceder con la descarga" + #~ msgid "Backup device missing" #~ msgstr "Dispositivo de respaldo perdido" @@ -2136,6 +1796,13 @@ msgstr "_Ver" #~ msgid "Unique identifier '%s' added" #~ msgstr "Identificador único '%s' agregado" +#~ 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" + #~ msgid "Thumbnail cannot be displayed" #~ msgstr "Miniatura no puede mostrarse" @@ -2145,9 +1812,38 @@ msgstr "_Ver" #~ msgid "images skipped" #~ msgstr "Imágenes saltadas" +#~ msgid "Using manually specified path" +#~ msgstr "Usando manualmente la ruta especifica" + #~ msgid "Preferences were changed." #~ msgstr "Las preferencias fueron cambiadas." +#~ msgid "No preferences needed to be changed." +#~ msgstr "Ninguna preferencia necesita ser cambiada." + +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Valor inválido de descargas de hoy.\n" + +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s ya se está ejecutando" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Detectado %(device)s con ruta %(path)s" + +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "Valor '%(value)s' es inválido" + +#, 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" + #~ msgid "Subsecond metadata not present in image" #~ msgstr "Metadato de sub-segundos no esta presente en la imagen" @@ -2168,6 +1864,9 @@ msgstr "_Ver" #~ msgid "Error in date time component. Value %s appears invalid" #~ msgstr "Error en el campo de fecha. El valor %s parece inválido" +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "<span weight=\"bold\" size=\"x-large\">Automatización</span>" + #~ msgid "<i>Example: /home/user/photos</i>" #~ msgstr "<i>Ejemplo: /home/user/photos</i>" @@ -2177,9 +1876,15 @@ msgstr "_Ver" #~ msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" #~ msgstr "<span weight=\"bold\" size=\"x-large\">Renombrar imagen</span>\t" +#~ msgid "Automation" +#~ msgstr "Automatización" + #~ msgid "Exit program after completion of successful download" #~ msgstr "Salir del programa al completar exitosamente la descarga" +#~ msgid "Error Log" +#~ msgstr "Registro de error" + #~ msgid "Ignore" #~ msgstr "Ignorar" @@ -2192,6 +1897,25 @@ msgstr "_Ver" #~ msgid "Select a folder in which to backup images" #~ msgstr "Seleccione una carpeta para respaldar las imágenes" +#~ 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'" + +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "La descarga empezó desde %s" + +#~ msgid "Automatically start download is true" +#~ msgstr "Iniciar automaticamente la descarga está activa" + +#, python-format +#~ msgid "About %(minutes)i:%(seconds)02i minutes remaining" +#~ msgstr "Resta cerca de %(minutes)i:%(seconds)02i minutos" + +#~ msgid "Automatically start download is false" +#~ msgstr "Iniciar automaticamente la descarga está desactivada" + #~ 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" @@ -2223,6 +1947,28 @@ msgstr "_Ver" #~ msgid "Specify what to do when there are no backup devices." #~ msgstr "Especificar que hacer cuando no hay dispositivos de respaldo." +#~ 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." + +#~ 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." + +#~ msgid "Backing up error" +#~ msgstr "Error en copia de seguridad" + +#~ msgid "These preferences are not well formed:" +#~ msgstr "Estas preferencias no están bien formadas:" + #~ 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" @@ -2231,6 +1977,16 @@ msgstr "_Ver" #~ msgid "error generating name with component %s" #~ msgstr "Error generando nombre con componente %s" +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Fallo al recibir capacidades del servidor pynotify" + +#~ 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." + #~ msgid "This device has no images to download from." #~ msgstr "El dispositivo no tiene imágenes para descargar." @@ -2298,6 +2054,26 @@ msgstr "_Ver" #~ msgid "Copyright Damon Lynch 2007-09" #~ msgstr "Copyright © Damon Lynch 2007-09" +#~ msgid "Warning:" +#~ msgstr "Aviso:" + +#~ 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." + +#~ msgid "Some preferences will be reset." +#~ msgstr "Algunas preferencias serán restablecidas." + +#~ msgid "There is an error in the program preferences." +#~ msgstr "Hay un error en las preferencis del programa." + #~ msgid "" #~ "The subfolder preferences entered are invalid and cannot be used.\n" #~ "They will be reset to their default values." @@ -2326,18 +2102,70 @@ msgstr "_Ver" #~ "configurarla en modo PTP. Si esto no es posible, considere usar un lector de " #~ "tarjetas.</i>" +#~ msgid "Starting downloads" +#~ msgstr "Iniciando descargas" + +#~ msgid "Job Code entered" +#~ msgstr "Código de trabajo ingresado" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "Iniciando descargas que han sido esperadas por un Código de trabajo" + +#~ msgid "Prompting for Job Code" +#~ msgstr "Pidiendo un Código de trabajo" + +#~ msgid "Job Code not entered" +#~ msgstr "Código de trabajo no introducido" + +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s seleccionado para descargar de" + +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "Siempre se descargará de este dispositivo o partición" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s rechazado como dispositivo de descarga" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "Jamás se descargará de este dispositivo o partición" + #~ msgid "Enter a new job code, or select a previous one." #~ msgstr "Entre un nuevo código de trabajo o seleccione uno previo." #~ msgid "Enter a new job code." #~ msgstr "Entre un nuevo código de trabajo." +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Preguntando si usar o no %s" + #~ msgid "Should this device or partition be used to download images from?" #~ msgstr "¿Deberían bajarse imágenes de este dispositivo o partición?" +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Dispositivo %(device)s (%(path)s) ignorado" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Preguntando por código de trabajo, no volver a preguntar" + +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Restableciendo valor a cero.\n" + +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Restableciendo a medianoche.\n" + +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "Valor preferencial de 'Inicio del día' corrupto.\n" + #~ msgid "Error in Download Subfolder preferences" #~ msgstr "Error en las preferencias de la Subcarpeta de Descargas" +#~ msgid "Resetting to default values." +#~ msgstr "Restableciendo a los valores por defecto." + #~ msgid "The subfolder preferences had some unnecessary values removed." #~ msgstr "" #~ "Se han removido innecesariamente algunos valores de las preferencias de la " @@ -2359,6 +2187,13 @@ msgstr "_Ver" #~ "subcarpetas.</i>" #~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Por favor, revise las preferencias, reinicie el programa e intente de nuevo." + +#~ msgid "" #~ "Image filename could not be properly generated. Check to ensure there is " #~ "sufficient image metadata." #~ msgstr "" @@ -2407,6 +2242,13 @@ msgstr "_Ver" #~ msgid "Image has no thumbnail" #~ msgstr "La imagen no tiene miniatura" +#, python-format +#~ msgid "Source: %(source)s" +#~ msgstr "Origen: %(source)s" + +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Copyright Damon Lynch 2007-10" + #~ msgid "" #~ "Images detected with the same filenames, but taken at different times:" #~ msgstr "" @@ -2421,6 +2263,9 @@ msgstr "_Ver" #~ "Primera imagen: %(image1)s %(image1_date_time)s:%(image1_subseconds)s\n" #~ "Segunda imagen: %(image2)s %(image2_date_time)s:%(image2_subseconds)s" +#~ msgid "Error:" +#~ msgstr "Error:" + #~ msgid "" #~ "Sorry, the Download Folder does not exist. Please create the folder, or " #~ "modify your preferences" @@ -2428,6 +2273,9 @@ msgstr "_Ver" #~ "Lo sentimos, la Carpeta de Descarga no existe. Por favor, cree la carpeta, o " #~ "modifique sus preferencias" +#~ msgid "Problem with Download Folder" +#~ msgstr "Problema con la Carpeta de Descarga" + #~ msgid "" #~ "Sorry, the Download Folder exists but cannot be written to. Please check the " #~ "folder's permissions, or modify your preferences" @@ -2440,6 +2288,22 @@ msgstr "_Ver" #~ msgstr "Dispositivo de imagen: %s\n" #, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Origen: %s\n" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Destino: %s" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Error: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "El directorio de destino no puede ser creado: %(directory)s\n" + +#, python-format #~ msgid "" #~ "Source: %(source)s\n" #~ "Destination: %(destination)s\n" @@ -2447,6 +2311,9 @@ msgstr "_Ver" #~ "Origen: %(source)s\n" #~ "Destino: %(destination)s\n" +#~ msgid "Could not create temporary download directory" +#~ msgstr "No se pudo crear el directorio de descarga temporal" + #, python-format #~ msgid "" #~ "Sorry, this image location does not exist:\n" @@ -2474,16 +2341,39 @@ msgstr "_Ver" #~ msgid "Image filename could not be generated" #~ msgstr "No se pudo generar el nombre del archivo de imagen" +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "El número de almacenados no se actualizó, pues se está haciendo una descarga " +#~ "actualmente." + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "El número de descargas de hoy no se actualizó, pues se está haciendo una " +#~ "descarga actualmente." + #~ msgid "Problem with Image Location Folder" #~ msgstr "Problema con Ubicación de Carpeta de Imagen" #~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Advertencia: el servidor de notificaciones del entorno de escritorio no está " +#~ "configurado correctamente." + +#~ msgid "_Report a Problem..." +#~ msgstr "_Reportar problema..." + +#~ 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 ubicaciones, por ejemplo: " #~ "discos duros externos." +#~ msgid "\n" +#~ msgstr "\n" + #, python-format #~ msgid "" #~ "First photo: %(image1)s %(image1_date_time)s:%(image1_subseconds)s\n" @@ -2492,6 +2382,10 @@ msgstr "_Ver" #~ "Primera foto: %(image1)s %(image1_date_time)s:%(image1_subseconds)s\n" #~ "Segunda foto: %(image2)s %(image2_date_time)s:%(image2_subseconds)s" +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Dispositivo: %s\n" + #~ msgid "Photo already exists" #~ msgstr "Foto ya existe" @@ -2514,5 +2408,127 @@ msgstr "_Ver" #~ msgstr "videos saltados" #, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "" +#~ "Escaneo del dispositivo completo: no se encuentran %(filetypes)s en " +#~ "%(device)s" + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Escaneo del dispositivo completo: se encontro %(number)s %(filetypes)s en " +#~ "%(device)s" + +#, python-format #~ msgid "0 of %(number)s %(filetypes)s" #~ msgstr "0 de %(number)s %(filetypes)s" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format +#~ msgid "%(noFiles)s %(filetypes)s downloaded" +#~ msgstr "%(noFiles)s %(filetypes)s descargados" + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Origen: %(source)s\n" +#~ "Destino: %(destination)s\n" +#~ "%(problem)s" + +#, python-format +#~ msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" +#~ msgstr "%(number)s de %(total)s %(filetypes)s (%(remaining)s restantes)" + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Error: %(inst)s" + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Foto: %(source)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Foto: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" + +#~ msgid "Downloading From Cameras" +#~ msgstr "Descargando desde las camaras" + +#~ msgid "_Show this message again" +#~ msgstr "_Mostrar este mensaje de nuevo" + +#~ msgid "Date" +#~ msgstr "Fecha" + +#~ msgid "File" +#~ msgstr "Archivo" + +#~ msgid "Status" +#~ msgstr "Estado" + +#~ msgid "Type" +#~ msgstr "Tipo" + +#~ msgid "Path" +#~ msgstr "Ruta" + +#~ msgid "Preview" +#~ msgstr "Vista previa" + +#, python-format +#~ msgid "%(number)s %(numberdownloaded)s" +#~ msgstr "%(number)s %(numberdownloaded)s" + +#, python-format +#~ msgid "%(filetype)s downloaded" +#~ msgstr "%(filetype)s descargados" + +#~ msgid "_Resume" +#~ msgstr "_Reanudar" + +#~ msgid "_Download All" +#~ msgstr "_Descargar tod" + +#~ msgid "Select All Vi_deos" +#~ msgstr "Seleccionar todos los ví_deos" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Seleccionar todas las fo_tos" + +#~ msgid "Select _All" +#~ msgstr "Seleccionar _todo" + +#~ msgid "_Device" +#~ msgstr "_Dispositivo" + +#~ msgid "_Filename" +#~ msgstr "Nombre de _archivo" + +#~ msgid "_Preview" +#~ msgstr "Vista _previa" + +#~ msgid "_Size" +#~ msgstr "_Tamaño" + +#~ msgid "_Type" +#~ msgstr "_Tipo" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "" +#~ "Descargas directas desde una cámara puede que no funcionen o funcionen mal" + +#~ msgid "Could not delete photo or video from device" +#~ msgstr "No se pudo borrar foto o video del dispositivo" + +#~ msgid "Exit program if download completes without any warnings or errors" +#~ msgstr "Salir del programa si se completa la descarga sin avisos ni errores" @@ -7,249 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-10-22 21:26-0500\n" -"PO-Revision-Date: 2010-11-03 12:42+0000\n" -"Last-Translator: Ersplus <ersplus@free.fr>\n" +"POT-Creation-Date: 2011-04-04 00:18-0500\n" +"PO-Revision-Date: 2011-04-10 23:41+0000\n" +"Last-Translator: Tubuntu <Unknown>\n" "Language-Team: French <fr@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: 2010-12-05 16:48+0000\n" -"X-Generator: Launchpad (build Unknown)\n" +"X-Launchpad-Export-Date: 2011-04-11 01:01+0000\n" +"X-Generator: Launchpad (build 12757)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6353 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:103 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:456 -msgid "New York" -msgstr "New York" - -#: rapid/rapid.py:457 -msgid "Manila" -msgstr "Manille" - -#: rapid/rapid.py:457 -msgid "Prague" -msgstr "Prague" - -#: rapid/rapid.py:457 -msgid "Helsinki" -msgstr "Helsinki" - -#: rapid/rapid.py:457 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:458 -msgid "Tehran" -msgstr "Téhéran" - -#: rapid/rapid.py:458 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:458 -msgid "Paris" -msgstr "Paris" - -#: rapid/rapid.py:458 -msgid "Berlin" -msgstr "Berlin" - -#: rapid/rapid.py:458 -msgid "Sydney" -msgstr "Sydney" - -#: rapid/rapid.py:459 -msgid "Budapest" -msgstr "Budapest" - -#: rapid/rapid.py:459 -msgid "Rome" -msgstr "Rome" - -#: rapid/rapid.py:459 -msgid "Moscow" -msgstr "Moscou" - -#: rapid/rapid.py:459 -msgid "Delhi" -msgstr "Delhi" - -#: rapid/rapid.py:459 -msgid "Warsaw" -msgstr "Varsovie" - -#: rapid/rapid.py:460 -msgid "Jakarta" -msgstr "Jakarta" - -#: rapid/rapid.py:460 -msgid "Madrid" -msgstr "Madrid" - -#: rapid/rapid.py:460 -msgid "Stockholm" -msgstr "Stockholm" - -#: rapid/rapid.py:493 -msgid "Invalid Downloads Today value.\n" -msgstr "Valeur de 'Transferts journaliers' invalide.\n" - -#: rapid/rapid.py:494 -msgid "Resetting value to zero.\n" -msgstr "Remise à zéro de la valeur.\n" - -#: rapid/rapid.py:533 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "La valeur de la préférence « Début de la journée » est corrompue.\n" - -#: rapid/rapid.py:534 -msgid "Resetting to midnight.\n" -msgstr "Réinialisation à minuit.\n" - -#: rapid/rapid.py:560 -msgid "Error in Photo Rename preferences" -msgstr "Erreur dans les préférences de renommage des photos" - -#: rapid/rapid.py:592 rapid/rapid.py:1714 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Désolé, il y a une erreur dans cette préférence :\n" - -#: rapid/rapid.py:603 -msgid "Resetting to default values." -msgstr "Réinitialisation aux valeurs par défaut" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:678 rapid/renamesubfolderprefs.py:199 -msgid "Job code" -msgstr "Étiquette de transfert" - -#: rapid/rapid.py:746 -msgid "Error in Video Rename preferences" -msgstr "Erreur dans les préférences de renommage des vidéos" - -#: rapid/rapid.py:764 -msgid "Error in Photo Download Subfolders preferences" -msgstr "Erreur dans les préférences des sous-dossiers de transfert de photos" - -#: rapid/rapid.py:781 -msgid "Error in Video Download Subfolders preferences" -msgstr "Erreur dans les préférences des sous-dossiers de transfert de vidéos" - -#: rapid/rapid.py:814 rapid/rapid.py:1545 -msgid "photos and videos" -msgstr "photos et vidéos" - -#: rapid/rapid.py:816 rapid/rapid.py:1555 rapid/rapid.py:1683 -msgid "photos" -msgstr "photos" - -#: rapid/rapid.py:949 -msgid "Select a folder to download photos to" -msgstr "Sélectionnez le dossier de destination" - -#: rapid/rapid.py:967 -msgid "Select a folder to download videos to" -msgstr "Sélectionnez un dossier vers lequel transférer vos vidéos" - -#: rapid/rapid.py:1049 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Sélectionnez un dossier contenant %(file_types)s" - -#: rapid/rapid.py:1071 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "Séléctionnez un dossier dans lequel sauvegarder %(file_types)s" - -#. 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:1152 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" -"<i><b>Attention :</b> Il n'y a pas assez de métadonnées pour générer " -"correctement le nom. Utilisez d'autres options de renommage.</i>" - -#: rapid/rapid.py:1188 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" -msgstr "" -"<i><b>Attention :</b> Il n'y a pas suffisamment de métadonnées pour générer " -"les sous-dossiers correctement. Veuillez utiliser d'autres options pour " -"nommer les sous-dossiers.</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:1192 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Exemple : %s</i>" - -#: rapid/rapid.py:1218 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"Un transfert est en cours : la valeur de 'Transferts journaliers' ne sera " -"pas mise à jour." - -#: rapid/rapid.py:1234 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Un transfert est en cours : la valeur du nombre stocké ne sera pas mise à " -"jour." - -#: rapid/rapid.py:1264 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" -"Les préférences de dossier %(filetype)s ont des valeurs inutiles qui ont été " -"enlevées." - -#. Preferences list is now empty -#: rapid/rapid.py:1269 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" -"Les préférences de dossier %(filetype)s entrées sont invalides et ne peuvent " -"être utilisées.\n" -"Elles vont être réinitialiseées à leurs valeurs par défaut." - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1283 rapid/rapid.py:1557 -msgid "photo" -msgstr "photo" - -#: rapid/rapid.py:1284 rapid/rapid.py:1552 -msgid "video" -msgstr "vidéo" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1521 -msgid "externaldrive1" -msgstr "disqueexterne1" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1523 -msgid "externaldrive2" -msgstr "disqueexterne2" - -#: rapid/rapid.py:1547 rapid/rapid.py:1681 -msgid "photos or videos" -msgstr "photos ou vidéos" - -#: rapid/rapid.py:1550 -msgid "videos" -msgstr "vidéos" - -#: rapid/rapid.py:1562 +#: rapid/rapid.py:108 #, python-format msgid "" "%(date)s\n" @@ -258,847 +31,172 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1564 +#: rapid/rapid.py:110 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1567 -#, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" - -#: rapid/rapid.py:1574 +#: rapid/rapid.py:113 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1602 rapid/rapid.py:2278 -msgid "subfolder and filename" -msgstr "Sous-dossier et nom de fichier" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:144 +msgid "Device" +msgstr "Volume" -#: rapid/rapid.py:1604 rapid/rapid.py:2280 -msgid "filename" -msgstr "nom de fichier" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:158 +msgid "Size" +msgstr "Taille" -#: rapid/rapid.py:1606 rapid/rapid.py:2282 -msgid "subfolder" -msgstr "sous-dossier" +#: rapid/rapid.py:161 +msgid "Download Progress" +msgstr "Progression du transfert" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1697 +#: rapid/rapid.py:974 msgid "scanning..." msgstr "Détection en cours..." -#: rapid/rapid.py:1812 -msgid "The following download path could not be created:\n" -msgstr "Le chemin de transfert suivant n'a pas pu être créé :\n" - -#: rapid/rapid.py:1813 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1814 rapid/rapid.py:1815 rapid/rapid.py:1830 -#: rapid/rapid.py:1831 rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Download cannot proceed" -msgstr "Impossible de procéder au transfert" - -#: rapid/rapid.py:1828 rapid/rapid.py:4999 -msgid "There is an error in the program preferences." -msgstr "Il y a une erreur dans les préférences concernant le programme." - -#: rapid/rapid.py:1829 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Merci de vérifier les préférences, de redemarrer le programme et d'essayer " -"encore." - -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2006 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2017 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Le périphérique a été entièrement scanné : %(number)s %(filetypes)s ont été " -"trouvés sur %(device)s" - -#: rapid/rapid.py:2024 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "" -"Le périphérique a été entièrement scanné : aucun %(filetypes)s n'a été " -"trouvé sur %(device)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:2045 -msgid "The device can now be safely removed" -msgstr "Le volume peut maintenant être retiré en toute sécurité" - -#: rapid/rapid.py:2051 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s transférés" - -#: rapid/rapid.py:2054 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "erreur lors du transfert de %(noFiles)s %(filetypes)s" - -#: rapid/rapid.py:2057 rapid/rapid.py:5792 -msgid "warnings" -msgstr "avertissements" - -#: rapid/rapid.py:2059 rapid/rapid.py:5796 -msgid "errors" -msgstr "erreurs" - -#: rapid/rapid.py:2089 -#, python-format -msgid "Source: %s\n" -msgstr "Source : %s\n" - -#: rapid/rapid.py:2091 -#, python-format -msgid "Device: %s\n" -msgstr "Périphérique: %s\n" - -#: rapid/rapid.py:2092 -#, python-format -msgid "Destination: %s" -msgstr "Destination %s" - -#: rapid/rapid.py:2093 rapid/rapid.py:2096 -msgid "Could not create temporary download directory" -msgstr "Le dossier de transfert temporaire n'a pas pu être créé" +#: rapid/rapid.py:1678 +msgid "Download" +msgstr "Transférer" -#: rapid/rapid.py:2096 -msgid "Error:" -msgstr "Erreur :" +#: rapid/rapid.py:1681 +msgid "Pause" +msgstr "Pause" -#: rapid/rapid.py:2120 -msgid "Backup path does not exist" -msgstr "Le chemin de sauvegarde n'existe pas" - -#: rapid/rapid.py:2121 -#, python-format -msgid "The path %s could not be created" -msgstr "Le chemin %s n'a pas pu être créé" - -#: rapid/rapid.py:2122 -msgid "No backups can occur" -msgstr "Aucune sauvegarde possible" - -#: rapid/rapid.py:2151 +#: rapid/rapid.py:1794 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" msgstr "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +"Ces répertoires de téléchargement ne sont pas valides:\n" +"%(folder1)s\n" +"%(folder2)s" -#: rapid/rapid.py:2182 rapid/rapid.py:2528 rapid/rapid.py:2563 -#: rapid/rapid.py:2591 rapid/rapid.py:2622 rapid/rapid.py:2641 +#: rapid/rapid.py:1797 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" -msgstr "" -"Source : %(source)s\n" -"Destination : %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2197 -msgid "Please check your system and try again." -msgstr "Vérifiez votre système et essayez à nouveau" - -#: rapid/rapid.py:2217 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" -"Des photos portant le même nom mais prises à différents moments ont été " -"détectées" - -#: rapid/rapid.py:2257 -msgid "Photo has already been downloaded" -msgstr "La photo a déjà été téléchargée" - -#: rapid/rapid.py:2258 rapid/rapid.py:2657 -#, python-format -msgid "Source: %(source)s" -msgstr "Source : %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2456 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "" -"Un nouveau jour a commencé - remise à zero de la numérotation « Transferts " -"journaliers »" - -#: rapid/rapid.py:2527 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Une sauvegarde de %(file_type)s existe déjà" - -#: rapid/rapid.py:2531 -#, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "Sauvegarde de %(file_type)s écrasée" - -#: rapid/rapid.py:2535 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "%(file_type)s non sauvé sur %(volume)s" - -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "%(file_type)s non sauvé" - -#: rapid/rapid.py:2560 rapid/rapid.py:2588 rapid/rapid.py:2621 -#: rapid/rapid.py:2640 -msgid "Backing up error" -msgstr "Erreur lors de la sauvegarde" - -#: rapid/rapid.py:2561 rapid/rapid.py:2589 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Le dossier de destination n'a pas pu être créé %(directory)s\n" - -#: rapid/rapid.py:2565 rapid/rapid.py:2624 -#, python-format -msgid "Error: %(inst)s" -msgstr "Erreur : %(inst)s" - -#: rapid/rapid.py:2566 rapid/rapid.py:2594 rapid/rapid.py:2625 -#: rapid/rapid.py:2644 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "%(file_type)s n'a pas été sauvé." - -#: rapid/rapid.py:2593 rapid/rapid.py:2643 -#, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Erreur : %(errno)s %(strerror)s" - -#: rapid/rapid.py:2656 -#, python-format -msgid "%(file_type)s could not be backed up" -msgstr "%(file_type)s n'a pas pu être sauvé" - -#: rapid/rapid.py:2659 -msgid "No suitable backup volume was found" -msgstr "Aucun volume de sauvegarde aproprié n'a été trouvé" - -#: rapid/rapid.py:2661 -msgid "A backup location was not found" -msgstr "Un emplacement de sauvegarde n'a pas été trouvé" - -#: rapid/rapid.py:2715 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." +"This download folder is invalid:\n" +"%s" msgstr "" +"Ce répertoire de téléchargement n'est pas valide:\n" +"%s" -#: rapid/rapid.py:2788 -#, python-format -msgid "Download has started from %s" -msgstr "Le transfert a débuté depuis %s" - -#: rapid/rapid.py:2799 -#, python-format -msgid "Attempting to download %s files" -msgstr "Tentative de téléchargement de %s fichiers" +#: rapid/rapid.py:1798 +msgid "Download cannot proceed" +msgstr "Impossible de procéder au transfert" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2831 rapid/rapid.py:2898 +#: rapid/rapid.py:1957 #, python-format msgid "%(number)s of %(total)s %(filetypes)s" msgstr "%(number)s sur %(total)s %(filetypes)s" -#: rapid/rapid.py:2894 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" -msgstr "%(number)s sur %(total)s %(filetypes)s (%(remaining)s restants)" - -#: rapid/rapid.py:2919 rapid/rapid.py:2923 -msgid "Could not delete photo or video from device" -msgstr "Impossible de supprimer la photo ou vidéo du périphérique" - -#: rapid/rapid.py:2920 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" -msgstr "" -"Photo : %(source)s\n" -"Erreur : %(errno)s %(strerror)s" - -#: rapid/rapid.py:2924 -#, python-format -msgid "Photo: %(source)s" -msgstr "Photo : %(source)s" - -#: rapid/rapid.py:2926 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "Suprression de %(number)i %(filetypes)s du périphérique" - -#: rapid/rapid.py:2939 -#, python-format -msgid "Download complete from %s" -msgstr "Transfert terminé depuis %s" - -#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. -#: rapid/rapid.py:3054 rapid/rapid.py:3523 -msgid "Device" -msgstr "Volume" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3059 rapid/rapid.py:3512 -msgid "Size" -msgstr "Taille" - -#: rapid/rapid.py:3062 -msgid "Download Progress" -msgstr "Progression du transfert" - -#: rapid/rapid.py:3150 -msgid "Downloading From Cameras" -msgstr "Téléchargement depuis les appareils photo" - -#: rapid/rapid.py:3156 -msgid "Downloading directly from a camera may work poorly or not at all" -msgstr "" -"Télécharger directement depuis un appareil photo peut mal fonctionner, voire " -"non fonctionner." - -#: rapid/rapid.py:3157 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." -msgstr "" -"Télécharger depuis un lecteur de carte marche toujours et est généralement " -"plus rapide. Il est fortement recommandé d'utiliser un lecteur de carte." - -#: rapid/rapid.py:3171 -msgid "_Show this message again" -msgstr "Continuer d'afficher ce me_ssage" - -#: rapid/rapid.py:3206 -msgid "Device Detected" -msgstr "Périphérique détecté" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3215 -msgid "" -"Should this device or partition be used to download photos or videos from?" -msgstr "" -"Est-ce qu'il faut télécharger photos et vidéos à partir de ce périphérique " -"ou cette partition ?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "_Remember this choice" -msgstr "Se _Souvenir de ce choix" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3271 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s a été séléctionné comme source de transfert" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3274 -msgid "This device or partition will always be used to download from" -msgstr "" -"Ce périphérique ou cette partition sera toujours utilisé comme source de " -"transfert" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3277 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s a été rejeté comme source de transfert" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3280 -msgid "This device or partition will never be used to download from" -msgstr "" -"Ce périphérique ou cette partition ne sera jamais utilisé comme source de " -"transfert" - -#: rapid/rapid.py:3287 -msgid "Remove all Job Codes?" -msgstr "Supprimer toutes les étiquettes de transfert ?" - -#: rapid/rapid.py:3304 -msgid "Should all Job Codes be removed?" -msgstr "" -"Êtes-vous sûr de vouloir supprimer toutes les étiquettes de transfert ?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3332 -msgid "Enter a Job Code" -msgstr "Entrer une étiquette de transfert" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a new Job Code, or select a previous one" -msgstr "" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3354 -msgid "Enter a new Job Code" -msgstr "" - -#: rapid/rapid.py:3359 rapid/rapid.py:4534 -msgid "Job Code:" -msgstr "Étiquette de transfert" - -#: rapid/rapid.py:3406 -msgid "Job Code entered" -msgstr "Étiquette de transfert entrée" - -#: rapid/rapid.py:3408 -msgid "Job Code not entered" -msgstr "Étiquettes de transfert non renseignée" - -#: rapid/rapid.py:3458 -msgid "Status" -msgstr "État" - -#: rapid/rapid.py:3466 -msgid "Type" -msgstr "Type" - -#: rapid/rapid.py:3475 rapid/rapid.py:4961 rapid/rapid.py:4963 -msgid "Photo" -msgstr "Photo" - -#: rapid/rapid.py:3477 -msgid "File" -msgstr "Fichier" - -#: rapid/rapid.py:3492 -msgid "Job Code" -msgstr "" - -#: rapid/rapid.py:3502 -msgid "Date" -msgstr "Date" - -#: rapid/rapid.py:3534 rapid/renamesubfolderprefs.py:195 -msgid "Filename" -msgstr "Nom de fichier" - -#: rapid/rapid.py:3545 -msgid "Path" -msgstr "Chemin" - -#: rapid/rapid.py:3955 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s a été téléchargé avec succès" - -#: rapid/rapid.py:3957 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s n'a pas été téléchargé" - -#: rapid/rapid.py:3959 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s a été téléchargé avec des avertissements" - -#: rapid/rapid.py:3961 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" -msgstr "" -"%(filetype)s a été téléchargé mais il y a eu des problèmes de sauvegarde" +#: rapid/rapid.py:2302 rapid/preferencesdialog.py:825 rapid/rpdfile.py:120 +msgid "photos" +msgstr "photos" -#: rapid/rapid.py:3963 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "%(filetype)s n'a ni été téléchargé ni sauvegardé" +#: rapid/rapid.py:2304 rapid/rpdfile.py:115 +msgid "videos" +msgstr "vidéos" -#: rapid/rapid.py:3965 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s est prêt à être téléchargé" +#: rapid/rapid.py:2308 +msgid "Free space:" +msgstr "Espace libre :" -#: rapid/rapid.py:3967 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2320 #, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "%(filetype)s va être téléchargé" +msgid "(%(file_type)s)" +msgstr "(%(file_type)s)" -#: rapid/rapid.py:3969 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2324 #, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s sera téléchargé avec des avertissements" +msgid "%(free)s %(file_type)s" +msgstr "%(free)s %(file_type)s" -#: rapid/rapid.py:3971 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s ne peut être téléchargé" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2329 +msgid "; " +msgstr ", " -#: rapid/rapid.py:4341 -msgid "Preview" -msgstr "Aperçu" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2334 +msgid "." +msgstr "." -#: rapid/rapid.py:4556 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "" - -#: rapid/rapid.py:4928 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2340 #, python-format -msgid "%(free)s available" -msgstr "" +msgid "%(free)s free" +msgstr "%(free)s disponibles" #. user manually specified backup location -#: rapid/rapid.py:4934 +#: rapid/rapid.py:2346 #, python-format msgid "Backing up to %(path)s" -msgstr "" +msgstr "Sauvegarde sur %(path)s" -#: rapid/rapid.py:4939 +#: rapid/rapid.py:2351 #, python-format msgid "%(freespace)s. %(backuppaths)s." -msgstr "" - -#: rapid/rapid.py:4948 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" -"Désolé, ce périphérique n'existe pas :\n" -"%(path)s\n" -"\n" -"Veuillez résoudre le problème, ou modifier vos préférences." +msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:4952 -msgid "Problem with Device Location Folder" -msgstr "" +#: rapid/rapid.py:2479 rapid/rpdfile.py:247 +msgid "Photo" +msgstr "Photo" -#: rapid/rapid.py:4961 +#: rapid/rapid.py:2481 rapid/rpdfile.py:267 msgid "Video" msgstr "Vidéo" -#: rapid/rapid.py:4968 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "Le dossier de téléchargement de %(file_type)s n'existe pas.\n" - -#: rapid/rapid.py:4977 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "" -"Le dossier de téléchargement de %(file_type)s existe mais on ne peut y " -"écrire.\n" - -#: rapid/rapid.py:4982 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" -"Désolé, des problèmes ont été rencontrés avec vos dossiers de " -"téléchargement. Veuillez réparer les problèmes ou modifier les préférences.\n" -"\n" - -#: rapid/rapid.py:4985 -msgid "Problem with Download Folder" -msgstr "Problème avec le dossier de transfert" - -#: rapid/rapid.py:4987 -msgid "Problem with Download Folders" -msgstr "Problèmes avec les dossiers de téléchargement." - -#: rapid/rapid.py:5000 -msgid "Some preferences will be reset." -msgstr "" -"Certaines préférences vont être réinitalisées à leurs valeurs par défaut." - -#: rapid/rapid.py:5033 -msgid "Displaying warning about downloading directly from camera" -msgstr "" - -#: rapid/rapid.py:5043 -#, python-format -msgid "Prompting whether to use %s" -msgstr "Affichage du choix d'utilisation ou non de %s" - -#: rapid/rapid.py:5070 -msgid "Prompting for Job Code" -msgstr "En attende de l'étiquette de transfert" - -#: rapid/rapid.py:5074 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Affiche déjà pour l'étiquette de transfert, n'affichera plus" - -#: rapid/rapid.py:5091 -msgid "Starting downloads" -msgstr "Démarrage du transfert" - -#. autostart is true -#: rapid/rapid.py:5095 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "" -"Démarrage des téléchargements qui ont attendu une étiquette de transfert" - -#: rapid/rapid.py:5142 +#: rapid/rapid.py:2490 #, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "Création du dossier de destination des photos %(folder)s" - -#: rapid/rapid.py:5147 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "" -"Échec de la création du dossier de destination par défaut des photos " -"%(folder)s" - -#: rapid/rapid.py:5151 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "Création du dossier de destination des viédos %(folder)s" - -#: rapid/rapid.py:5156 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "" -"Échec de la création du dossier de destination par défaut des vidéos " -"%(folder)s" - -#: rapid/rapid.py:5181 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" -msgstr "" -"Une version plus récente de l'application a précédemment été lancée sur cet " -"ordinateur.\n" -"\n" - -#: rapid/rapid.py:5183 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"Les préférences de l'application ont l'air d'être correctes, veuillez tout " -"de même les vérifier afin d'assurer le bon déroulement de l'opération." - -#: rapid/rapid.py:5185 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "" -"Désolé, certaines préférences ne sont pas valides et seront réinitialisées." - -#: rapid/rapid.py:5186 -msgid "Warning:" -msgstr "Avertissement :" - -#: rapid/rapid.py:5191 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." -msgstr "L'application a été mise à jour, vérification des préférences." - -#: rapid/rapid.py:5198 -msgid "Preferences were modified." -msgstr "Les préférences ont été modifiées." - -#: rapid/rapid.py:5199 -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 "" -"Cette version de l'application utilise des préférences différentes de " -"l'ancienne version. Vos préférences ont été mises à jour.\n" -"Veuillez les vérifier afin d'assurer le bon fonctionnement de l'application." - -#: rapid/rapid.py:5203 -msgid "No preferences needed to be changed." -msgstr "Aucun changement des préférences n'a été nécessaire." - -#: rapid/rapid.py:5205 -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 "" -"Cette version de l'application utilise des préférences différentes de " -"l'ancienne version. Certaines de vos préférences antérieures sont invalides " -"et n'ont pas été mises à jour. Elles vont être réinitialisées." - -#: rapid/rapid.py:5215 -msgid "Problem using pynotify." -msgstr "Problème d'utilisation de pynotify" - -#: rapid/rapid.py:5231 -msgid "Failed to receive pynotify server capabilities." -msgstr "Echec de la reception des possibilités du serveur pynotify" - -#: rapid/rapid.py:5242 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Avertissement : le serveur de notification de l'environnement de bureau est " -"incorrectement configuré." - -#: rapid/rapid.py:5290 -msgid "and" -msgstr "et" - -#: rapid/rapid.py:5295 -msgid "Using backup devices" -msgstr "Utilisation des volumes de sauvegarde" - -#: rapid/rapid.py:5297 -msgid "Using backup device" -msgstr "Utilisation du volume de sauvegarde" - -#: rapid/rapid.py:5299 -msgid "No backup devices detected" -msgstr "Aucun volume de sauvegarde détécté" +msgid "%(file_type)s download folder does not exist" +msgstr "%(file_type)s répertoires de téléchargement n'existe pas" -#: rapid/rapid.py:5349 rapid/rapid.py:5511 +#: rapid/rapid.py:2492 rapid/rapid.py:2506 rapid/rapid.py:2519 #, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Périphérique %(device)s (%(path)s) ignoré" +msgid "Folder: %s" +msgstr "Répertoire: %s" -#: rapid/rapid.py:5470 +#: rapid/rapid.py:2504 #, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Le volume %(device)s a été détecté avec le chemin d'accès %(path)s" +msgid "%(file_type)s download folder is invalid" +msgstr "%(file_type)s répertoire de téléchargement n'est pas valide" -#: rapid/rapid.py:5474 -msgid "Automatically start download is true" -msgstr "Le démarrage automatique du transfert est activé" - -#: rapid/rapid.py:5476 -msgid "Automatically start download is false" -msgstr "Le démarrage automatique du transfert est désactivé" - -#: rapid/rapid.py:5529 -msgid "Using manually specified path" -msgstr "Utilisation du chemin d'accès renseigne manuellement" - -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5597 +#: rapid/rapid.py:2517 #, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" -msgstr "" +msgid "%(file_type)s download folder is not writable" +msgstr "%(file_type)s répertoire de téléchargement protégé en écriture" -#: rapid/rapid.py:5613 -msgid "D_ownload Selected" -msgstr "" - -#: rapid/rapid.py:5713 rapid/rapid.py:5764 -msgid "All downloads complete" -msgstr "Tous les transferts sont terminés" - -#: rapid/rapid.py:5728 -msgid "MB/s" -msgstr "Mo/s" - -#: rapid/rapid.py:5738 -msgid "About 1 second remaining" -msgstr "Environ 1 seconde restante" - -#: rapid/rapid.py:5740 -#, python-format -msgid "About %i seconds remaining" -msgstr "Environ %i secondes restantes" - -#: rapid/rapid.py:5742 -msgid "About 1 minute remaining" -msgstr "Environ 1 minute 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:5747 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Environ %(minutes)i:%(seconds)02i restantes" - -#: rapid/rapid.py:5767 rapid/rapid.py:5773 rapid/rapid.py:5779 -#: rapid/rapid.py:5785 rapid/rapid.py:5790 rapid/rapid.py:5794 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" - -#: rapid/rapid.py:5769 rapid/rapid.py:5781 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s téléchargé" - -#: rapid/rapid.py:5775 rapid/rapid.py:5787 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "" - -#: rapid/rapid.py:5955 -msgid "_Resume" -msgstr "_Reprendre" - -#: rapid/rapid.py:5958 -msgid "_Download All" -msgstr "" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:5967 -msgid "_Pause" -msgstr "_Pause" - -#: rapid/rapid.py:6079 -msgid "Download device settings preferences were changed." -msgstr "" - -#: rapid/rapid.py:6091 -msgid "Backup preferences were changed." -msgstr "Les préférences de sauvegarde ont été modifiées." - -#: rapid/rapid.py:6097 -msgid "Subfolder and filename preferences were changed." -msgstr "" -"Les préférences de sous-dossier et de nom de fichier ont été modifiées." - -#: rapid/rapid.py:6108 -msgid "Download folder preferences were changed." -msgstr "" - -#: rapid/rapid.py:6307 -msgid "Goodbye" -msgstr "Au-revoir" +#: rapid/rapid.py:2592 +msgid "Thumbnails" +msgstr "Aperçus" #. 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:6318 +#: rapid/rapid.py:2633 #, python-format msgid "" "display program information on the command line as the program runs " @@ -1107,585 +205,1240 @@ msgstr "" "affiche les informations de l'application sur la ligne de commande lorsque " "l'application est active (défaut: %default)" -#: rapid/rapid.py:6319 +#: rapid/rapid.py:2634 msgid "display debugging information when run from the command line" msgstr "Affiche les informations de débogage en mode console" -#: rapid/rapid.py:6320 +#: rapid/rapid.py:2635 msgid "only output errors to the command line" msgstr "n'affiche que les erreurs sur la ligne de commande" #. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6322 +#: rapid/rapid.py:2637 msgid "list photo and video file extensions the program recognizes and exit" msgstr "" "Liste des extensions de fichiers photo et vidéo reconnues par le programme" -#: rapid/rapid.py:6323 +#: rapid/rapid.py:2638 msgid "reset all program settings and preferences and exit" msgstr "Réinitialise tous les paramètres et préférences du programme" -#: rapid/rapid.py:6337 +#: rapid/rapid.py:2651 msgid "Photos:" msgstr "Photos :" -#: rapid/rapid.py:6337 +#: rapid/rapid.py:2651 msgid "Videos:" msgstr "Vidéos :" -#: rapid/rapid.py:6342 +#: rapid/rapid.py:2656 #, python-format msgid "and %s" msgstr "et %s" -#: rapid/rapid.py:6350 +#: rapid/rapid.py:2664 msgid "All settings and preferences have been reset" msgstr "Tous les paramètres et préférences ont été réinitialisés" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6354 rapid/rapid.py:6355 rapid/rapid.py:6357 -#: rapid/rapid.py:6362 rapid/rapid.py:6366 -msgid "Using" -msgstr "En utilisation" - -#: rapid/rapid.py:6359 -msgid "\n" -msgstr "\n" +#: rapid/rapid.py:2673 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." +msgstr "" +"Fonctionalité de transfert des vidéos désactivée.\n" +"Afin de transférer des vidéos, installez hachoir metadata et kaa metadata " +"pour python." -#. this application is already running -#: rapid/rapid.py:6383 +#: rapid/copyfiles.py:136 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:346 #, python-format -msgid "%s is already running" -msgstr "%s déjà actif" +msgid "" +"%(problem)s\n" +"File: %(file)s" +msgstr "" +"%(problem)s\n" +"Fichier: %(file)s" + +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Périphérique détecté" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "" +"Est-ce qu'il faut télécharger photos et vidéos à partir de ce périphérique " +"ou cette partition ?" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "Se _Souvenir de ce choix" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Date/heure" -#: rapid/renamesubfolderprefs.py:194 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Texte" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Nom de fichier" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Métadonnées" -#: rapid/renamesubfolderprefs.py:197 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Séquences" -#: rapid/renamesubfolderprefs.py:200 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:550 +msgid "Job code" +msgstr "Étiquette de transfert" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Date de l'image" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:151 msgid "Video date" msgstr "Date de la vidéo" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Aujourd'hui" -#: rapid/renamesubfolderprefs.py:203 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Hier" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:205 +#: rapid/generatenameconfig.py:155 msgid "Download time" -msgstr "" +msgstr "Temps de transfert" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:207 +#: rapid/generatenameconfig.py:157 msgid "Name + extension" msgstr "Nom + extension" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:209 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Nom" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:211 +#: rapid/generatenameconfig.py:161 msgid "Extension" msgstr "Extension" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:213 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Numéro de l'image" -#: rapid/renamesubfolderprefs.py:214 +#: rapid/generatenameconfig.py:164 msgid "Video number" -msgstr "" +msgstr "Numéro de vidéo" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:216 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Ouverture" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:218 +#: rapid/generatenameconfig.py:168 msgid "ISO" msgstr "ISO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:220 +#: rapid/generatenameconfig.py:170 msgid "Exposure time" msgstr "Vitesse d'obturation" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:222 +#: rapid/generatenameconfig.py:172 msgid "Focal length" msgstr "Longueur focale" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:224 +#: rapid/generatenameconfig.py:174 msgid "Camera make" msgstr "Marque de l'appareil" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:226 +#: rapid/generatenameconfig.py:176 msgid "Camera model" msgstr "Modèle de l'appareil" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:228 +#: rapid/generatenameconfig.py:178 msgid "Short camera model" msgstr "Modèle de l'appareil (version courte)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:230 +#: rapid/generatenameconfig.py:180 msgid "Hyphenated short camera model" msgstr "Nom court de l'appareil photo avec trait d'union" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:232 +#: rapid/generatenameconfig.py:182 msgid "Serial number" msgstr "Numéro de série" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:234 +#: rapid/generatenameconfig.py:184 msgid "Shutter count" msgstr "Nombre de déclenchements de l'obturateur" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:236 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Nom du propriétaire" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Codec" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Largeur" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Hauteur" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Longueur" -#: rapid/renamesubfolderprefs.py:241 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Images par seconde" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:243 +#: rapid/generatenameconfig.py:193 msgid "Downloads today" msgstr "Transferts journaliers" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:245 +#: rapid/generatenameconfig.py:195 msgid "Session number" msgstr "Numéro de session" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:247 +#: rapid/generatenameconfig.py:197 msgid "Subfolder number" msgstr "Numéro de sous-dossier" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:249 +#: rapid/generatenameconfig.py:199 msgid "Stored number" msgstr "Nombres stockés" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:251 +#: rapid/generatenameconfig.py:201 msgid "Sequence letter" msgstr "Séquence alphabétique" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:253 +#: rapid/generatenameconfig.py:203 msgid "All digits" msgstr "Tous les chiffres" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:255 +#: rapid/generatenameconfig.py:205 msgid "Last digit" msgstr "Dernier chiffre" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:257 +#: rapid/generatenameconfig.py:207 msgid "Last 2 digits" msgstr "2 derniers chiffres" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:259 +#: rapid/generatenameconfig.py:209 msgid "Last 3 digits" msgstr "3 derniers chiffres" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:261 +#: rapid/generatenameconfig.py:211 msgid "Last 4 digits" msgstr "4 derniers chiffres" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:263 +#: rapid/generatenameconfig.py:213 msgid "Original Case" msgstr "Casse originale" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:265 +#: rapid/generatenameconfig.py:215 msgid "UPPERCASE" msgstr "MAJUSCULES" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:267 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "minuscules" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Un chiffre" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Deux chiffres" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Trois chiffres" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Quatre chiffres" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Cinq chiffres" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Six chiffres" -#: rapid/renamesubfolderprefs.py:274 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "7 chiffres" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:276 +#: rapid/generatenameconfig.py:226 msgid "Subseconds" msgstr "Sous-secondes" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:278 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "AAAAMMJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:280 +#: rapid/generatenameconfig.py:230 msgid "YYYY-MM-DD" msgstr "AAA-MM-JJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:282 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "AAMMJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:284 +#: rapid/generatenameconfig.py:234 msgid "YY-MM-DD" msgstr "AA-MM-JJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:286 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "MM-JJ-AAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:288 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "MM-JJ-AA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:290 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "MMJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:292 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "JJMMAAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:294 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "JJMMAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:296 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "AAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:298 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "AA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:300 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:302 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "JJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:304 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "HHMMSS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:306 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "HHMM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:308 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "HH-MM-SS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:310 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "HH-MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:312 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "HH" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:314 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "MM (minutes)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:316 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "SS" -#: rapid/renamesubfolderprefs.py:801 +#: rapid/preferencesdialog.py:371 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "" +"Les préférences de sous-dossier ne devraient pas commencer avec un %s" + +#: rapid/preferencesdialog.py:373 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "" +"Les préférences de sous-dossier ne devraient pas se terminer avec un %s" + +#: rapid/preferencesdialog.py:377 #, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" +"Les préférences de sous-dossier ne devraient pas contenir deux %s consécutifs" + +#: rapid/preferencesdialog.py:390 rapid/preferencesdialog.py:673 +msgid "Remove all Job Codes?" +msgstr "Supprimer toutes les étiquettes de transfert ?" + +#: rapid/preferencesdialog.py:407 rapid/preferencesdialog.py:690 +msgid "Should all Job Codes be removed?" +msgstr "" +"Êtes-vous sûr de vouloir supprimer toutes les étiquettes de transfert ?" + +#: rapid/preferencesdialog.py:437 +msgid "Error in Photo Rename preferences" +msgstr "Erreur dans les préférences de renommage des photos" + +#: rapid/preferencesdialog.py:618 +msgid "Error in Video Rename preferences" +msgstr "Erreur dans les préférences de renommage des vidéos" + +#: rapid/preferencesdialog.py:639 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Erreur dans les préférences des sous-dossiers de transfert de photos" + +#: rapid/preferencesdialog.py:656 +msgid "Error in Video Download Subfolders preferences" +msgstr "Erreur dans les préférences des sous-dossiers de transfert de vidéos" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:715 +msgid "Enter a Job Code" +msgstr "Entrer une étiquette de transfert" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:732 +msgid "Enter a new Job Code, or select a previous one" +msgstr "" +"Séléctionnez une étiquette de transfert existante ou créez en une nouvelle" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:735 +msgid "Enter a new Job Code" +msgstr "Entrez une nouvelle étiquette de transfert" + +#: rapid/preferencesdialog.py:740 +msgid "Job Code:" +msgstr "Étiquette de transfert" + +#: rapid/preferencesdialog.py:823 rapid/rpdfile.py:110 +msgid "photos and videos" +msgstr "photos et vidéos" + +#: rapid/preferencesdialog.py:992 +msgid "Select a folder to download photos to" +msgstr "Sélectionnez le dossier de destination" + +#: rapid/preferencesdialog.py:1010 +msgid "Select a folder to download videos to" +msgstr "Sélectionnez un dossier vers lequel transférer vos vidéos" + +#: rapid/preferencesdialog.py:1101 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Sélectionnez un dossier contenant %(file_types)s" + +#: rapid/preferencesdialog.py:1123 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "Séléctionnez un dossier dans lequel sauvegarder %(file_types)s" + +#. 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/preferencesdialog.py:1207 msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" msgstr "" -"La préférence '%(key)s' est invalude.\n" -"Valeurs attendues : %(value)s" +"<i><b>Attention :</b> Il n'y a pas assez de métadonnées pour générer " +"correctement le nom. Utilisez d'autres options de renommage.</i>" -#: rapid/renamesubfolderprefs.py:808 +#: rapid/preferencesdialog.py:1258 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Attention :</b> Il n'y a pas suffisamment de métadonnées pour générer " +"les sous-dossiers correctement. Veuillez utiliser d'autres options pour " +"nommer les sous-dossiers.</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/preferencesdialog.py:1261 #, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "La préférence « %(value)s » est invalide" +msgid "<i>Example: %s</i>" +msgstr "<i>Exemple : %s</i>" -#: rapid/renamesubfolderprefs.py:812 -msgid "These preferences are not well formed:" -msgstr "Les préférences suivantes ne sont pas bien formattées :" +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1351 +#, python-format +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." +msgstr "" +"Les préférences de dossier %(filetype)s entrées sont invalides et ne peuvent " +"être utilisées.\n" +"Elles vont être réinitialiseées à leurs valeurs par défaut." + +#. check subfolder preferences for bad values +#: rapid/preferencesdialog.py:1365 rapid/rpdfile.py:122 rapid/rpdfile.py:246 +msgid "photo" +msgstr "photo" -#: rapid/renamesubfolderprefs.py:1525 +#: rapid/preferencesdialog.py:1366 rapid/rpdfile.py:117 rapid/rpdfile.py:266 +msgid "video" +msgstr "vidéo" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1637 +msgid "externaldrive1" +msgstr "disqueexterne1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1639 +msgid "externaldrive2" +msgstr "disqueexterne2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "New York" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manille" + +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Prague" + +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinki" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Téhéran" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Paris" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlin" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sydney" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Budapest" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Rome" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moscou" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Delhi" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Varsovie" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jakarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madrid" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Stockholm" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:339 +msgid "subfolder" +msgstr "sous-dossier" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:337 +msgid "filename" +msgstr "nom de fichier" + +#: rapid/problemnotification.py:80 #, python-format -msgid "Subfolder preferences should not start with a %s" +msgid "Date time value %s appears invalid." +msgstr "La valeur de date et heure %s semble non valable." + +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "Le nom de fichier n'a pas d'extension." + +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "Le nom du fichier n'a pas de composante unique." + +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." +msgstr "Erreur lors de la génération de la composante %s." + +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" +msgstr "%(filetype)s metadonné(e) illisible(s)" + +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" +msgstr "%(filetype)s %(area)s n'a pu être généré" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "Une erreur s'est produite lors de la copie de %(filetype)s" + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "%(filetype)s existe déjà" + +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." msgstr "" -"Les préférences de sous-dossier ne devraient pas commencer avec un %s" +"%(filetype)s n'a pu être sauvegardé car aucun emplacement approprié nà pu " +"être trouvé." -#: rapid/renamesubfolderprefs.py:1527 +#: rapid/problemnotification.py:102 #, python-format -msgid "Subfolder preferences should not end with a %s" +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." msgstr "" -"Les préférences de sous-dossier ne devraient pas se terminer avec un %s" +"%(image1)s à été prise le %(image1_date)s à %(image1_time)s, et %(image2)s " +"le %(image2_date)s à %(image2_time)s." -#: rapid/renamesubfolderprefs.py:1531 +#: rapid/problemnotification.py:103 #, python-format -msgid "Subfolder preferences should not contain two %s one after the other" +msgid "%(filetype)s was already downloaded" +msgstr "%(filetype)s était déjà téléchargé" + +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." msgstr "" -"Les préférences de sous-dossier ne devraient pas contenir deux %s consécutifs" +"La dernière modification du fichier existant %(filetype)s a été effectuée le " +"%(date)s à %(time)s. L'identifiant unique '%(identifier)s' ajouté." + +#: rapid/problemnotification.py:108 +#, python-format +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "" +"La dernière modification du fichier existant %(filetype)s a été effectuée le " +"%(date)s à %(time)s." + +#: rapid/problemnotification.py:109 +#, python-format +msgid "There is no data with which to name the %(filetype)s." +msgstr "Il n'y a aucune donnée pour nommer le %(filetype)s." + +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" +msgstr "Erreur : %(errorno)s %(strerror)s" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "Les métadonnées sont peut-être corrompues" + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "" +"Le nom de fichier, l'extension et l'information Exif indiquent qu'il a déjà " +"été téléchargé." + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr " Il a été archivé sur %(volume)s" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr " Il a été archivé sur ce périphérique: " + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "%s, " + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "%(volumes)s et %(final_volume)s." + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" +"Des photos ayant des noms de fichiers indentiques mais ayant été prises à " +"des moments différents ont été détectées : %(details)s" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "" +"Une erreur c'est produite lors de l'archivage sur %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "Une erreur c'est produite lors de l'archivage sur %(volume)s." + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "" +"Des erreurs se sont produites lors de la sauvegarde sur le péripérique de " +"sauvegarde suivant : " + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "%(volume)s (%(inst)s), " + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "%(volume)s, " + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "%(volumes)s et %(volume)s (%(inst)s)." + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "%(volumes)s et %(volume)s." + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "Une sauvegarde existe déjà sur %(volume)s." + +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "Des sauvegardes existent déjà aux emplacements suivants : " + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "Sauvegarde écrasée sur %(volume)s." + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "Sauvegardes écrasées sur les périphériques suivants : " + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "" +"Une erreur s'est produite lors de la création des répertoires sur " +"%(volume)s : %(inst)s." + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "" +"Des erreurs se sont produites lors de la création des répertoires sur les " +"périphériques de sauvegarde suivants : " + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "%(previousproblem)s Ainsi que, %(newproblem)s" + +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr " En outre, il y avait des %(problems)s." + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr " En outre, il y avait un %(problem)s." + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "Le %(type)s de métadonnées est manquant." + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "la métadonnée suivante est manquante: " + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "%(missing_metadata_elements)s et %(final_missing_metadata_element)s." -#: rapid/glade3/rapid.glade.h:1 +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "Problème lors de la génération du sous-dossier et du nom de fichier" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "Problème lors de la génération du sous-dossier et du nom de fichier" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "Problèmes lors de la génération de %s" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "Problème lors de la génération de %s" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "%(filetype)s existe déjà, mais cela a été archivé" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "" +"Une erreur s'est produite lors de la copie de %(filetype)s, mais cela a été " +"archivé" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "Plusieurs problèmes ont été rencontrés" + +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "" +"Des photos portant le même nom mais prises à différents moments ont été " +"détectées" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "il y a eu des erreurs lors de la sauvegarde" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "Il y a eu des erreurs lors de la sauvegarde" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "il y a eu une erreur lors de la sauvegarde" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "Il y a eu une erreur lors de la sauvegarde" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "%(previousproblem)s, et %(backinguperror)s" + +#: rapid/rpdfile.py:112 +msgid "photos or videos" +msgstr "photos ou vidéos" + +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" + +#: rapid/subfolderfile.py:194 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Source : %(source)s\n" +"Destination : %(destination)s" + +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" +msgstr "La photo a déjà été téléchargée" + +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" +msgstr "Source : %(source)s" + +#: rapid/subfolderfile.py:335 +msgid "subfolder and filename" +msgstr "Sous-dossier et nom de fichier" + +#: rapid/subfolderfile.py:373 +msgid "Failed to create download subfolder" +msgstr "Echec de création de sous-répertoire de téléchargement" + +#: rapid/subfolderfile.py:374 +#, python-format +msgid "Path: %s" +msgstr "Chemin: %s" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "À propos ..." + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "Tout sélectionner" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "Sélectionner toutes les photos" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "Sélectionner toutes les vidéos" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Transfert / Pause" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "Obtenir de l'aide en ligne..." + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "Faire un don..." + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "Fichier suivant" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "Fichier précédent" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "Quitter" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "Actualiser" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "Signaler un bogue…" + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "Séléctionner tous les fic_hiers ayant une étiquette de transfert" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "Séléctionner tous les fichiers n'ayant pas d'étiquette de transfert" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "Traduire cette Application..." + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "Désélectionner tout" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "Tout _cocher" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Effacer les transferts terminés" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" +msgstr "_Transférer" + +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "Journal des _erreurs" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Fichier" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "_Aide" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "_Inclure dans le transfert" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Faire une _donation..." + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Sélection" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Traduire cette application..." + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" +msgstr "To_ut déselectionner" + +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "A_ffichage" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " hh:mm" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "<b>Sauvegarde</b>" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Compatibilité avec d'autres systèmes d'exploitation</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" -msgstr "" +msgstr "<b>Périphériques</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Dossier de destination</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Sous-dossiers de transfert</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Exemple</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Étiquettes de transfert</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "<b>Renommage des phtoos</b>" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "<b>Photo et Vidéo Conflits de noms</b>" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Automatisation de l'application</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Séquences numériques</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/media/disqueexterne/Photos</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Exemple : /home/utilisateur/Images</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Exemple :</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Nouveau :</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 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\">Automatisation</span>" - -#: rapid/glade3/rapid.glade.h:22 +#: rapid/glade3/prefs.ui.h:20 msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Sauvegarde</span>\t" -#: rapid/glade3/rapid.glade.h:23 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" -msgstr "" +msgstr "<span weight=\"bold\" size=\"x-large\">Périphériques</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Gestion des erreurs</span>" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Étiquettes de transfert</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Divers</span>" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Dossiers de destination des " "photos</span>" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Renommage des photos</span>\t" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.h:27 msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Options de renommage</span>" -#: rapid/glade3/rapid.glade.h:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Dossiers de destination des " "vidéos</span>" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Renommage des vidéos</span>\t" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Ajouter un identifiant unique" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Détecter automatiquement les volumes de stockage amovibles" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Détecter automatiquement les volumes de sauvegarde" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Détecter les périphériques automatiquement" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Automatisation" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Sauvegarde" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Localisation de la sauvegarde :" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "Sauvegarder les photos et les vidéos lors du transfert" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1694,7 +1447,7 @@ msgstr "" "transférées seront automatiquement crées dans ce dossier selon la structure " "spécifiée ci-dessous." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." @@ -1703,24 +1456,20 @@ msgstr "" "téléchargées seront automatiquement créés dans ce dossier en utilisant la " "structure spécifiée ci-dessous." -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Copyright Damon Lynch 2007-10" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Début du jour :" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" "Supprimer des photos et vidéos de l'appareil à la fin du téléchargement" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Périphériques" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1744,38 +1493,35 @@ msgstr "" "pas du tout, essayez le mode PTP. Si cela n'est pas possible, considérez " "l'utilisation d'un lecteur de cartes.</i>" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Transfert / Pause" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Dossier de destination :" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Transferts journaliers :" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Gestion des erreurs" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Journal des erreurs" - -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" msgstr "" -"Quitter le programme après un transfert réussi, sans erreur ni avertissement" +"Quitter l'application même si des avertissements ou des erreurs ont été " +"signalés pendant le transfert" + +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" +msgstr "Quitter l'application après un transfert réussi" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" "Si la détection automatique est désactivée, choisissez un emplacement pour " "la sauvegarde." -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." @@ -1783,7 +1529,7 @@ msgstr "" "Si vous désactiver la détection automatique, choisissez l'emplacement exact " "des images et des vidéos." -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1793,127 +1539,65 @@ msgstr "" "le volume complet sera analysé. Sur des volumes de capacité importante, cela " "peut prendre du temps." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "Transférez vos photos et vidéos de façon simple et fiable" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Étiquettes de transfert" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Emplacement :" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "Divers" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Écraser" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "Dossiers de photos" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "Renommage des photos" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "Dossier de sauvegarde des photos :" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Préférences : Rapid Photo Downloader" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "S_upprimer tout" -#: rapid/glade3/rapid.glade.h:72 -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 est un logiciel libre; vous pouvez le distribuer " -"et/ou le modifier sous les termes de la licence GNU General Public License " -"comme publiée par la Free Software Foundation; soit dans la version 2 de " -"cette license, ou (selon votre choix) dans les termes d'une version " -"postérieure. \n" -"\n" -"Ce programme est distribué dans l’espoir qu’il sera utile, mais SANS AUCUNE " -"GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou " -"D’ADAPTATION A UN OBJET PARTICULIER. Pour plus de détails, voir la Licence " -"Publique Générale GNU.\n" -"\n" -"Un exemplaire de la Licence Publique Générale GNU doit être fourni avec ce " -"programme ; si ce n’est pas le cas, écrivez à la Free Software Foundation " -"Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis." - -#: rapid/glade3/rapid.glade.h:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Options de renommage" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "Sé_lectionner Aucun" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Sélectionner toutes les Pho_tos" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Sélectionner toutes les Vi_déos" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "Sélectionner t_out" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Passer" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Sauter le transfert" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " -"install the <i>kaa metadata</i> package for python." +"install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " +"python." msgstr "" -"Désolé, la fonctionnalité de téléchargement de vidéos est désactivée. Pour " -"télécharger des vidéos, veuillez installer le package <i>kaa metadata</ i> " -"pour python." +"Désolé, fonctionnalité de téléchargement vidéo invalide. Pour installer des " +"vidéos, veuillez installer les paquets pour python <i>hachoir-metadata</i> " +"et <i>kaa-metadata</i>." -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1921,8 +1605,14 @@ msgid "" "used for backups. For each device you wish to use for backing up to, create " "a folder in it with one of these names.</i>" msgstr "" +"Spécifier le dossier dans lequel l'archivage est stocké sur le périphérique. " +" \n" +"\n" +"<i>Note: ceci sera également utilisé pour déterminer si oui ou non le " +"périphérique est utilisé pour les sauvegardes. Créez un répertoire avec un " +"de ces noms, dans chaque périphérique à utiliser pour sauvegarder.</i>" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1930,134 +1620,87 @@ msgstr "" "Spécifiez l'heure au format 24h à laquelle la séquence <i>Transferts " "journaliers</i> doit être réinitialisée." -#: rapid/glade3/rapid.glade.h:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." msgstr "" +"Spécifier si les noms de photo, de vidéo et de dossier doivent avoir des " +"caractères supprimés n'étant pas autorisés par d'autre systèmes " +"d'exploitation." -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Démarrer le transfert au démarrage de l'application" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" -msgstr "" +msgstr "Commencer le transfert lors de l'insertion d'un périphérique" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Nombre stocké :" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Enlever les caractères incompatibles" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "" "Synchroniser les séquences numériques pour les paires d'images RAW + JPEG" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" -msgstr "" +msgstr "Démonter le périphérique de stockage après un transfert réussi" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Dossiers Vidéo" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" -msgstr "" +msgstr "Renommage des vidéos" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" -msgstr "" +msgstr "Dossier de sauvegarde des vidéos :" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." msgstr "" +"Lorsqu'une photo ou une vidéo portant le même nom a déjà été transférée, " +"choisissez si vous souhaitez sauter le transfert ou si vous préférez ajouter " +"un identifiant unique." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." msgstr "" +"Lors de l'archivage, choisir s'il faut écraser ou passer un fichier ayant le " +"même nom sur le périphérique d'archivage." -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." msgstr "" +"Vous pouvez archiver vos photos et vidéos vers des emplacements multiples " +"dès lors qu'elles sont téléchargées, sur différents disques durs par exemple." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Ajouter..." -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Effacer les transferts terminés" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "Journal des _erreurs" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Fichier" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "Aide en _ligne" - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "_Aide" - -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Faire une _donation..." - -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Chemin" - -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "A_perçu" - -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Rapporter un problème..." - -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "" - -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "" - -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Traduire cette application..." +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Transférez vos photos et vidéos de façon simple et fiable" -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "" - -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "A_ffichage" +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Désolé, il y a une erreur dans cette préférence :\n" #, python-format #~ msgid "Device scan complete: found %(number)s images on %(device)s" @@ -2122,6 +1765,9 @@ msgstr "A_ffichage" #~ msgid "Backup image already exists" #~ msgstr "Une sauvegarde existe déjà" +#~ msgid "Backing up error" +#~ msgstr "Erreur lors de la sauvegarde" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2149,10 +1795,16 @@ msgstr "A_ffichage" #~ "Image : %(image)s\n" #~ "Problème : %(problem)s" +#~ msgid "warnings" +#~ msgstr "avertissements" + #, python-format #~ msgid "%s images skipped" #~ msgstr "%s images non prises en compte" +#~ msgid "errors" +#~ msgstr "erreurs" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2163,6 +1815,9 @@ msgstr "A_ffichage" #~ "Destination : %(destination)s\n" #~ "Erreur : %(errno)s %(strerror)s" +#~ msgid "The device can now be safely removed" +#~ msgstr "Le volume peut maintenant être retiré en toute sécurité" + #~ msgid "Image has no thumbnail" #~ msgstr "L'image n'a pas d'aperçu" @@ -2176,6 +1831,18 @@ msgstr "A_ffichage" #~ msgid "Image already exists" #~ msgstr "L'image existe déjà" +#~ msgid "" +#~ "A newer version of this program was previously run on this computer.\n" +#~ "\n" +#~ msgstr "" +#~ "Une version plus récente de l'application a précédemment été lancée sur cet " +#~ "ordinateur.\n" +#~ "\n" + +#, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Transfert terminé depuis %s" + #~ msgid "Download copying error" #~ msgstr "Erreur de copie lors du transfert" @@ -2193,23 +1860,132 @@ msgstr "A_ffichage" #~ msgid "%s images downloaded" #~ msgstr "%s images transférées" +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Le transfert a débuté depuis %s" + +#~ msgid "Warning:" +#~ msgstr "Avertissement :" + +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "" +#~ "Désolé, certaines préférences ne sont pas valides et seront réinitialisées." + +#~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "Les préférences de l'application ont l'air d'être correctes, veuillez tout " +#~ "de même les vérifier afin d'assurer le bon déroulement de l'opération." + +#~ msgid "No preferences needed to be changed." +#~ msgstr "Aucun changement des préférences n'a été nécessaire." + +#~ 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 "" +#~ "Cette version de l'application utilise des préférences différentes de " +#~ "l'ancienne version. Vos préférences ont été mises à jour.\n" +#~ "Veuillez les vérifier afin d'assurer le bon fonctionnement de l'application." + +#~ msgid "Preferences were modified." +#~ msgstr "Les préférences ont été modifiées." + +#~ msgid "" +#~ "This version of the program is newer than the previously run version. " +#~ "Checking preferences." +#~ msgstr "L'application a été mise à jour, vérification des préférences." + +#~ msgid "Problem using pynotify." +#~ msgstr "Problème d'utilisation de pynotify" + +#~ 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 "" +#~ "Cette version de l'application utilise des préférences différentes de " +#~ "l'ancienne version. Certaines de vos préférences antérieures sont invalides " +#~ "et n'ont pas été mises à jour. Elles vont être réinitialisées." + +#~ msgid "MB/s" +#~ msgstr "Mo/s" + +#~ msgid "Using manually specified path" +#~ msgstr "Utilisation du chemin d'accès renseigne manuellement" + +#~ msgid "Automatically start download is true" +#~ msgstr "Le démarrage automatique du transfert est activé" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Le volume %(device)s a été détecté avec le chemin d'accès %(path)s" + +#~ msgid "No backup devices detected" +#~ msgstr "Aucun volume de sauvegarde détécté" + +#~ msgid "Automatically start download is false" +#~ msgstr "Le démarrage automatique du transfert est désactivé" + +#~ msgid "and" +#~ msgstr "et" + +#~ msgid "Using backup device" +#~ msgstr "Utilisation du volume de sauvegarde" + +#~ msgid "Using backup devices" +#~ msgstr "Utilisation des volumes de sauvegarde" + +#~ msgid "All downloads complete" +#~ msgstr "Tous les transferts sont terminés" + #~ msgid "images skipped" #~ msgstr "Images non prises en compte" #~ msgid "_Download " #~ msgstr "_Transfert " +#, python-format +#~ msgid "About %(minutes)i:%(seconds)02i minutes remaining" +#~ msgstr "Environ %(minutes)i:%(seconds)02i restantes" + #~ msgid "images downloaded" #~ msgstr "Images transférées" +#, python-format +#~ msgid "About %i seconds remaining" +#~ msgstr "Environ %i secondes restantes" + +#~ msgid "About 1 minute remaining" +#~ msgstr "Environ 1 minute restante" + +#~ msgid "About 1 second remaining" +#~ msgstr "Environ 1 seconde restante" + +#~ msgid "_Pause" +#~ msgstr "_Pause" + #~ msgid "Preferences were changed." #~ msgstr "Les préférences ont été modifiées" +#~ msgid "Goodbye" +#~ msgstr "Au-revoir" + +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s déjà actif" + #~ msgid "list image file extensions the program recognizes and exit" #~ msgstr "" #~ "affiche les extensions de fichier reconnues par l'application et quitte " #~ "l'application" +#~ msgid "These preferences are not well formed:" +#~ msgstr "Les préférences suivantes ne sont pas bien formattées :" + #~ msgid "extension was specified but image name has no extension" #~ msgstr "" #~ "Un extension a été spécifiée mais le nom de l'image ne comporte aucune " @@ -2224,6 +2000,9 @@ msgstr "A_ffichage" #~ msgid "error generating name with component %s" #~ msgstr "Erreur dans la génération du nom avec le composant %s" +#~ msgid " " +#~ msgstr " " + #~ msgid "<b>Image Rename</b>" #~ msgstr "<b>Renommage des images</b>" @@ -2236,9 +2015,15 @@ msgstr "A_ffichage" #~ msgid "<b>Image Devices</b>" #~ msgstr "<b>Volume d'images</b>" +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "<span weight=\"bold\" size=\"x-large\">Automatisation</span>" + #~ msgid "<i>Example: /home/user/photos</i>" #~ msgstr "<i>Exemple : /home/utilisateur/photos</i>" +#~ msgid "Automation" +#~ msgstr "Automatisation" + #~ msgid "Backup folder name:" #~ msgstr "Nom du dossier de sauvegarde :" @@ -2283,12 +2068,45 @@ msgstr "A_ffichage" #~ "Si la détection automatique est désactivée, choisissez un emplacement pour " #~ "les images." +#~ msgid "Error Log" +#~ msgstr "Journal des erreurs" + #~ msgid "Report an error" #~ msgstr "Rapporter une erreur" #~ msgid "Report a warning" #~ msgstr "Rapporter un avertissement" +#~ 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 est un logiciel libre; vous pouvez le distribuer " +#~ "et/ou le modifier sous les termes de la licence GNU General Public License " +#~ "comme publiée par la Free Software Foundation; soit dans la version 2 de " +#~ "cette license, ou (selon votre choix) dans les termes d'une version " +#~ "postérieure. \n" +#~ "\n" +#~ "Ce programme est distribué dans l’espoir qu’il sera utile, mais SANS AUCUNE " +#~ "GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou " +#~ "D’ADAPTATION A UN OBJET PARTICULIER. Pour plus de détails, voir la Licence " +#~ "Publique Générale GNU.\n" +#~ "\n" +#~ "Un exemplaire de la Licence Publique Générale GNU doit être fourni avec ce " +#~ "programme ; si ce n’est pas le cas, écrivez à la Free Software Foundation " +#~ "Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis." + #~ msgid "Start downloading upon image device insertion" #~ msgstr "Démarrer le transfert lors de l'insertion d'un volume d'images" @@ -2304,12 +2122,21 @@ msgstr "A_ffichage" #~ "Spécifiez s'il faut enlever du nom des images et des dossiers tout caractère " #~ "non autorisé par d'autres systèmes d'exploitation." +#~ msgid "_Get Help Online..." +#~ msgstr "Aide en _ligne" + #~ msgid "_Photos" #~ msgstr "_Photos" #~ msgid "_Thumbnails" #~ msgstr "_Vignettes" +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Remise à zéro de la valeur.\n" + +#~ msgid "Resetting to default values." +#~ msgstr "Réinitialisation aux valeurs par défaut" + #~ msgid "Download Folder" #~ msgstr "Transfert" @@ -2363,9 +2190,23 @@ msgstr "A_ffichage" #~ "Il est possible de sauvegarder les photos sur des emplacements multiples, " #~ "différents du dossier de transfert (par exemple, des disques durs externes)." +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Valeur de 'Transferts journaliers' invalide.\n" + +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "" +#~ "Un nouveau jour a commencé - remise à zero de la numérotation « Transferts " +#~ "journaliers »" + #~ msgid "No backup device was detected." #~ msgstr "Aucun volume de sauvegarde n'a été détecté." +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Réinialisation à minuit.\n" + +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "La valeur de la préférence « Début de la journée » est corrompue.\n" + #, python-format #~ msgid "" #~ "Metadata is essential for generating subfolders / image names.\n" @@ -2392,6 +2233,21 @@ msgstr "A_ffichage" #~ "être utilisées.\n" #~ "Les valeurs par défaut seront utilisées." +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Merci de vérifier les préférences, de redemarrer le programme et d'essayer " +#~ "encore." + +#~ msgid "There is an error in the program preferences." +#~ msgstr "Il y a une erreur dans les préférences concernant le programme." + +#~ msgid "Some preferences will be reset." +#~ msgstr "" +#~ "Certaines préférences vont être réinitalisées à leurs valeurs par défaut." + #, python-format #~ msgid "%s metadata is not present in image" #~ msgstr "La métadonnée %s n'est pas présente dans l'image" @@ -2421,9 +2277,21 @@ msgstr "A_ffichage" #~ "difficilement voire pas du tout, essayez de le paramétrer en mode PTP. Si ce " #~ "n'est pas possible, utilisez un lecteur de cartes.</i>" +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "La préférence « %(value)s » est invalide" + #~ msgid "It may be corrupted" #~ msgstr "Il est peut-être corrompu" +#, python-format +#~ msgid "" +#~ "Preference key '%(key)s' is invalid.\n" +#~ "Expected one of %(value)s" +#~ msgstr "" +#~ "La préférence '%(key)s' est invalude.\n" +#~ "Valeurs attendues : %(value)s" + #~ msgid "Subsecond metadata not present in image" #~ msgstr "L'image ne contient pas la métadonnée sous-secondes" @@ -2435,6 +2303,15 @@ msgstr "A_ffichage" #~ "pour générer le nom de façon complète. Utilisez une autre option de " #~ "renommage.</i>" +#~ msgid "Starting downloads" +#~ msgstr "Démarrage du transfert" + +#~ msgid "Using" +#~ msgstr "En utilisation" + +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Echec de la reception des possibilités du serveur pynotify" + #~ msgid "" #~ "<i><b>Warning:</b> There is insufficient image metadata to fully generate " #~ "subfolders. Please use other subfolder naming options.</i>" @@ -2443,6 +2320,40 @@ msgstr "A_ffichage" #~ "des sous-dossiers vides. S'il vous plait utiliser un autre sous dossier en " #~ "nommant les options." +#~ msgid "Job Code not entered" +#~ msgstr "Étiquettes de transfert non renseignée" + +#~ msgid "Prompting for Job Code" +#~ msgstr "En attende de l'étiquette de transfert" + +#~ msgid "Job Code entered" +#~ msgstr "Étiquette de transfert entrée" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "" +#~ "Démarrage des téléchargements qui ont attendu une étiquette de transfert" + +#~ msgid "_Report a Problem..." +#~ msgstr "_Rapporter un problème..." + +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s a été séléctionné comme source de transfert" + +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "" +#~ "Ce périphérique ou cette partition sera toujours utilisé comme source de " +#~ "transfert" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s a été rejeté comme source de transfert" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "" +#~ "Ce périphérique ou cette partition ne sera jamais utilisé comme source de " +#~ "transfert" + #~ msgid "Enter a new job code, or select a previous one." #~ msgstr "" #~ "Saisissez une nouvelle étiquette de transfert, ou choisissez un précédemment " @@ -2457,6 +2368,10 @@ msgstr "A_ffichage" #~ "transfert ?" #, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Périphérique %(device)s (%(path)s) ignoré" + +#, python-format #~ msgid "Device scan complete: no images found on %s" #~ msgstr "Détection terminée : aucune image trouvée sur %s" @@ -2482,6 +2397,20 @@ msgstr "A_ffichage" #~ msgid "Delete images from image device upon download completion" #~ msgstr "Supprimer les images du volume après le transfert" +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Copyright Damon Lynch 2007-10" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Un transfert est en cours : la valeur de 'Transferts journaliers' ne sera " +#~ "pas mise à jour." + +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Un transfert est en cours : la valeur du nombre stocké ne sera pas mise à " +#~ "jour." + #~ msgid "" #~ "Images detected with the same filenames, but taken at different times:" #~ msgstr "" @@ -2507,6 +2436,24 @@ msgstr "A_ffichage" #~ "Destination : %(destination)s\n" #~ "Problème : %(problem)s" +#~ msgid "Could not create temporary download directory" +#~ msgstr "Le dossier de transfert temporaire n'a pas pu être créé" + +#~ msgid "Error:" +#~ msgstr "Erreur :" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Destination %s" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Erreur : %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Le dossier de destination n'a pas pu être créé %(directory)s\n" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2528,6 +2475,15 @@ msgstr "A_ffichage" #~ "Résolvez le problème ou modifiez vos préférences." #~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Avertissement : le serveur de notification de l'environnement de bureau est " +#~ "incorrectement configuré." + +#~ msgid "Problem with Download Folder" +#~ msgstr "Problème avec le dossier de transfert" + +#~ msgid "" #~ "Sorry, the Download Folder exists but cannot be written to. Please check the " #~ "folder's permissions, or modify your preferences" #~ msgstr "" @@ -2553,5 +2509,316 @@ msgstr "A_ffichage" #~ msgstr "Erreur dans les préférences concernant le sous-dossier de transfert" #, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Source : %s\n" + +#, python-format #~ msgid "Image device: %s\n" #~ msgstr "Volume d'images : %s\n" + +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Affichage du choix d'utilisation ou non de %s" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Affiche déjà pour l'étiquette de transfert, n'affichera plus" + +#~ msgid "\n" +#~ msgstr "\n" + +#, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "" +#~ "Le périphérique a été entièrement scanné : aucun %(filetypes)s n'a été " +#~ "trouvé sur %(device)s" + +#, python-format +#~ msgid "%(noFiles)s %(filetypes)s downloaded" +#~ msgstr "%(noFiles)s %(filetypes)s transférés" + +#, python-format +#~ msgid "%(noFiles)s %(filetypes)s failed to download" +#~ msgstr "erreur lors du transfert de %(noFiles)s %(filetypes)s" + +#~ msgid "The following download path could not be created:\n" +#~ msgstr "Le chemin de transfert suivant n'a pas pu être créé :\n" + +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Périphérique: %s\n" + +#~ msgid "No backups can occur" +#~ msgstr "Aucune sauvegarde possible" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Le chemin %s n'a pas pu être créé" + +#~ msgid "Backup path does not exist" +#~ msgstr "Le chemin de sauvegarde n'existe pas" + +#~ msgid "Please check your system and try again." +#~ msgstr "Vérifiez votre système et essayez à nouveau" + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Le périphérique a été entièrement scanné : %(number)s %(filetypes)s ont été " +#~ "trouvés sur %(device)s" + +#, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "%(file_type)s non sauvé sur %(volume)s" + +#, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Une sauvegarde de %(file_type)s existe déjà" + +#, python-format +#~ msgid "" +#~ "The %(filetype)s subfolder preferences had some unnecessary values removed." +#~ msgstr "" +#~ "Les préférences de dossier %(filetype)s ont des valeurs inutiles qui ont été " +#~ "enlevées." + +#, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "Sauvegarde de %(file_type)s écrasée" + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format +#~ msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" +#~ msgstr "%(number)s sur %(total)s %(filetypes)s (%(remaining)s restants)" + +#, python-format +#~ msgid "%(file_type)s could not be backed up" +#~ msgstr "%(file_type)s n'a pas pu être sauvé" + +#, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "%(file_type)s n'a pas été sauvé." + +#, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "%(file_type)s non sauvé" + +#, python-format +#~ msgid "Attempting to download %s files" +#~ msgstr "Tentative de téléchargement de %s fichiers" + +#~ msgid "No suitable backup volume was found" +#~ msgstr "Aucun volume de sauvegarde aproprié n'a été trouvé" + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Erreur : %(inst)s" + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Photo : %(source)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Photo : %(source)s\n" +#~ "Erreur : %(errno)s %(strerror)s" + +#~ msgid "Downloading From Cameras" +#~ msgstr "Téléchargement depuis les appareils photo" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "" +#~ "Télécharger directement depuis un appareil photo peut mal fonctionner, voire " +#~ "non fonctionner." + +#~ msgid "" +#~ "Downloading from a card reader always works and is generally much faster. It " +#~ "is strongly recommended to use a card reader." +#~ msgstr "" +#~ "Télécharger depuis un lecteur de carte marche toujours et est généralement " +#~ "plus rapide. Il est fortement recommandé d'utiliser un lecteur de carte." + +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "Suprression de %(number)i %(filetypes)s du périphérique" + +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Impossible de supprimer la photo ou vidéo du périphérique" + +#~ msgid "Path" +#~ msgstr "Chemin" + +#~ msgid "Date" +#~ msgstr "Date" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s n'a pas été téléchargé" + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s a été téléchargé avec succès" + +#~ msgid "File" +#~ msgstr "Fichier" + +#~ msgid "Status" +#~ msgstr "État" + +#~ msgid "Type" +#~ msgstr "Type" + +#, python-format +#~ msgid "%(filetype)s was downloaded but there were problems backing up" +#~ msgstr "" +#~ "%(filetype)s a été téléchargé mais il y a eu des problèmes de sauvegarde" + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s a été téléchargé avec des avertissements" + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s est prêt à être téléchargé" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s sera téléchargé avec des avertissements" + +#, python-format +#~ msgid "%(filetype)s is about to be downloaded" +#~ msgstr "%(filetype)s va être téléchargé" + +#, python-format +#~ msgid "%(filetype)s was neither downloaded nor backed up" +#~ msgstr "%(filetype)s n'a ni été téléchargé ni sauvegardé" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s ne peut être téléchargé" + +#~ msgid "Preview" +#~ msgstr "Aperçu" + +#, python-format +#~ msgid "" +#~ "Sorry, this device location does not exist:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Please resolve the problem, or modify your preferences." +#~ msgstr "" +#~ "Désolé, ce périphérique n'existe pas :\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Veuillez résoudre le problème, ou modifier vos préférences." + +#, python-format +#~ msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#~ msgstr "" +#~ "Le dossier de téléchargement de %(file_type)s existe mais on ne peut y " +#~ "écrire.\n" + +#, python-format +#~ msgid "The %(file_type)s Download Folder does not exist.\n" +#~ msgstr "Le dossier de téléchargement de %(file_type)s n'existe pas.\n" + +#~ msgid "Problem with Download Folders" +#~ msgstr "Problèmes avec les dossiers de téléchargement." + +#~ msgid "" +#~ "Sorry, problems were encountered with your download folders. Please fix the " +#~ "problems or modify the preferences.\n" +#~ "\n" +#~ msgstr "" +#~ "Désolé, des problèmes ont été rencontrés avec vos dossiers de " +#~ "téléchargement. Veuillez réparer les problèmes ou modifier les préférences.\n" +#~ "\n" + +#, python-format +#~ msgid "%(number)s %(numberdownloaded)s" +#~ msgstr "%(number)s %(numberdownloaded)s" + +#, python-format +#~ msgid "%(filetype)s downloaded" +#~ msgstr "%(filetype)s téléchargé" + +#~ msgid "_Resume" +#~ msgstr "_Reprendre" + +#~ msgid "_Show this message again" +#~ msgstr "Continuer d'afficher ce me_ssage" + +#, python-format +#~ msgid "Failed to create default video download folder %(folder)s" +#~ msgstr "" +#~ "Échec de la création du dossier de destination par défaut des vidéos " +#~ "%(folder)s" + +#, python-format +#~ msgid "Creating photo download folder %(folder)s" +#~ msgstr "Création du dossier de destination des photos %(folder)s" + +#, python-format +#~ msgid "Creating video download folder %(folder)s" +#~ msgstr "Création du dossier de destination des viédos %(folder)s" + +#, python-format +#~ msgid "Failed to create default photo download folder %(folder)s" +#~ msgstr "" +#~ "Échec de la création du dossier de destination par défaut des photos " +#~ "%(folder)s" + +#~ msgid "Subfolder and filename preferences were changed." +#~ msgstr "" +#~ "Les préférences de sous-dossier et de nom de fichier ont été modifiées." + +#~ msgid "Backup preferences were changed." +#~ msgstr "Les préférences de sauvegarde ont été modifiées." + +#~ msgid "Exit program if download completes without any warnings or errors" +#~ msgstr "" +#~ "Quitter le programme après un transfert réussi, sans erreur ni avertissement" + +#~ msgid "A backup location was not found" +#~ msgstr "Un emplacement de sauvegarde n'a pas été trouvé" + +#~ msgid "_Path" +#~ msgstr "_Chemin" + +#~ msgid "_Preview" +#~ msgstr "A_perçu" + +#~ msgid "Select _All" +#~ msgstr "Sélectionner t_out" + +#~ msgid "Select All Vi_deos" +#~ msgstr "Sélectionner toutes les Vi_déos" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Sélectionner toutes les Pho_tos" + +#~ msgid "Se_lect None" +#~ msgstr "Sé_lectionner Aucun" + +#~ msgid "" +#~ "Sorry, video downloading functionality disabled. To download videos, please " +#~ "install the <i>kaa metadata</i> package for python." +#~ msgstr "" +#~ "Désolé, la fonctionnalité de téléchargement de vidéos est désactivée. Pour " +#~ "télécharger des vidéos, veuillez installer le package <i>kaa metadata</ i> " +#~ "pour python." @@ -7,249 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" -"PO-Revision-Date: 2011-01-03 14:49+0000\n" +"POT-Creation-Date: 2011-04-10 19:59-0500\n" +"PO-Revision-Date: 2011-04-18 07:39+0000\n" "Last-Translator: A.J. Baudrez <a.baudrez@gmail.com>\n" "Language-Team: Dutch <nl@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: 2011-03-20 22:12+0000\n" -"X-Generator: Launchpad (build 12617)\n" +"X-Launchpad-Export-Date: 2011-04-21 06:12+0000\n" +"X-Generator: Launchpad (build 12883)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:104 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "New York" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "Manilla" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "Praag" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "Helsinki" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "Teheran" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "Parijs" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "Berlijn" - -#: rapid/rapid.py:463 -msgid "Sydney" -msgstr "Sydney" - -#: rapid/rapid.py:464 -msgid "Budapest" -msgstr "Boedapest" - -#: rapid/rapid.py:464 -msgid "Rome" -msgstr "Rome" - -#: rapid/rapid.py:464 -msgid "Moscow" -msgstr "Moskou" - -#: rapid/rapid.py:464 -msgid "Delhi" -msgstr "Delhi" - -#: rapid/rapid.py:464 -msgid "Warsaw" -msgstr "Warschau" - -#: rapid/rapid.py:465 -msgid "Jakarta" -msgstr "Jakarta" - -#: rapid/rapid.py:465 -msgid "Madrid" -msgstr "Madrid" - -#: rapid/rapid.py:465 -msgid "Stockholm" -msgstr "Stockholm" - -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" -msgstr "Ongeldige Downloads Vandaag waarde.\n" - -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" -msgstr "Waarde op nul terugzetten.\n" - -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "'Start of day' voorkeurswaarde is corrupt.\n" - -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" -msgstr "Terugzetten op middernacht.\n" - -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" -msgstr "Fout in de voorkeuren van Foto Hernoemen" - -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Sorry, deze voorkeuren bevatten een fout:\n" - -#: rapid/rapid.py:609 -msgid "Resetting to default values." -msgstr "Terugzetten naar de standaard waardes." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" -msgstr "Job code" - -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" -msgstr "Fout in de voorkeuren Video Hernoemen" - -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" -msgstr "Fout in de voorkeuren van Photo Download Subfolders" - -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" -msgstr "Fout in de voorkeuren Video Download Subfolders" - -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" -msgstr "foto's en video's" - -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 -msgid "photos" -msgstr "foto's" - -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "Duid een map aan om de foto's naar toe te downloaden" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" -msgstr "Selecteer een folder om de video's naar toe te downloaden" - -#: rapid/rapid.py:1055 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Selecteer een map die %(file_types)s bevat" - -#: rapid/rapid.py:1077 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "" -"Selecteer een map waar %(file_types)s naar toe gebackuped moeten worden" - -#. 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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" -"<i><b>Opgepast:</b> Er is onvoldoende metadata om een volledige naam aan te " -"maken. Gelieve andere hernoemings opties te gebruiken.</i>" - -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" -msgstr "" -"<i><b>Opgepast:</b> Er is onvoldoende metadata om volledige subfolders aan " -"te maken. Kies andere subfolder benoemings opties.</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:1198 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Voorbeeld: %s</i>" - -#: rapid/rapid.py:1224 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"'Downloads Vandaag' waarde niet aangepast, daar er momenteel een download " -"bezig is" - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Waarde opgeslagen nummer niet aangepast, daar er momenteel een download " -"bezig is" - -#: rapid/rapid.py:1270 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" -"Er werden overbodige waardes verwijderd van de voorkeuren voor de " -"%(filetype)s subfolder" - -#. Preferences list is now empty -#: rapid/rapid.py:1275 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" -"De voorkeuren voor de %(filetype)s subfolder zijn ongeldig en kunnen niet " -"gebruikt worden.\n" -"Ze zullen naar de standaard waardes worden teruggezet." - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" -msgstr "foto" - -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" -msgstr "video" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -msgid "externaldrive1" -msgstr "extern apparaat 1" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1529 -msgid "externaldrive2" -msgstr "extern apparaat 2" - -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" -msgstr "foto's of video's" - -#: rapid/rapid.py:1556 -msgid "videos" -msgstr "video's" - -#: rapid/rapid.py:1568 +#: rapid/rapid.py:109 #, python-format msgid "" "%(date)s\n" @@ -258,833 +31,264 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1570 +#: rapid/rapid.py:111 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1573 -#, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" - -#: rapid/rapid.py:1580 +#: rapid/rapid.py:114 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" -msgstr "subfolder en bestandsnaam" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:148 +msgid "Device" +msgstr "Apparaat" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" -msgstr "bestandsnaam" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:165 +msgid "Size" +msgstr "Grootte" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" -msgstr "subfolder" +#: rapid/rapid.py:168 +msgid "Download Progress" +msgstr "Downloadvoortgang" + +#: rapid/rapid.py:312 +#, python-format +msgid "%(device)s did not unmount" +msgstr "%(device)s werd niet ontkoppeld" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 +#: rapid/rapid.py:1091 msgid "scanning..." msgstr "Aan het scannen..." -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" -msgstr "Het volgende downloadpad kon niet aangemaakt worden:\n" - -#: rapid/rapid.py:1819 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 -msgid "Download cannot proceed" -msgstr "Download kan niet plaatsgrijpen" - -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." -msgstr "Er is een fout in de programma voorkeuren." - -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Gelieve de voorkeuren te controleren, het programma te herstarten en opnieuw " -"te proberen." - -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2019 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Apparaten scan afgelopen: %(number)s %(filetypes)s op %(device)s gevonden" - -#: rapid/rapid.py:2026 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "Apparaten scan afgelopen: geen %(filetypes)s gevonden op %(device)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:2047 -msgid "The device can now be safely removed" -msgstr "Het apparaat kan nu veilig verwijderd worden" - -#: rapid/rapid.py:2053 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s gedownload" - -#: rapid/rapid.py:2056 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "%(noFiles)s %(filetypes)s kon niet gedownload worden" - -#: rapid/rapid.py:2059 rapid/rapid.py:5901 -msgid "warnings" -msgstr "verwittigingen" - -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" -msgstr "fouten" - -#: rapid/rapid.py:2091 -#, python-format -msgid "Source: %s\n" -msgstr "Bron: %s\n" - -#: rapid/rapid.py:2093 -#, python-format -msgid "Device: %s\n" -msgstr "Apparaat: %s\n" - -#: rapid/rapid.py:2094 -#, python-format -msgid "Destination: %s" -msgstr "Doel: %s" - -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" -msgstr "Kon de tijdelijke downloadfolder niet aanmaken" +#: rapid/rapid.py:1807 +msgid "Download" +msgstr "Download" -#: rapid/rapid.py:2098 -msgid "Error:" -msgstr "Fout:" +#: rapid/rapid.py:1810 +msgid "Pause" +msgstr "Pauze" -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" -msgstr "Backup pad bestaat niet" - -#: rapid/rapid.py:2123 -#, python-format -msgid "The path %s could not be created" -msgstr "Het pad %s kon niet aangemaakt worden" - -#: rapid/rapid.py:2124 -msgid "No backups can occur" -msgstr "Backups kunnen niet plaatsgrijpen" - -#: rapid/rapid.py:2153 +#: rapid/rapid.py:1912 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" msgstr "" -"Bron: %(source)s\n" -"Doel: %(destination)s\n" -"%(problem)s" +"Deze downloadmappen zijn ongeldig:\n" +"%(folder1)s\n" +"%(folder2)s" -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 +#: rapid/rapid.py:1915 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" +"This download folder is invalid:\n" +"%s" msgstr "" -"Bron: %(source)s\n" -"Doel: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "Controlleer je systeem en probeer opnieuw" +"Deze downloadmap is ongeldig:\n" +"%s" -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" -"Foto's gevonden met dezelfde bestandsnaam, maar op een verschillend tijdstip " -"genomen" +#: rapid/rapid.py:1916 +msgid "Download cannot proceed" +msgstr "Download kan niet plaatsgrijpen" -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" -msgstr "Foto werd al eens gedownload" +#: rapid/rapid.py:2130 +msgid "About 1 second remaining" +msgstr "Ongeveer 1 seconde te gaan" -#: rapid/rapid.py:2260 rapid/rapid.py:2659 +#: rapid/rapid.py:2132 #, python-format -msgid "Source: %(source)s" -msgstr "Bron: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "" -"Nieuwe dag begonnen - volgnummer 'Downloads Vandaag' aan het terugzetten" +msgid "About %i seconds remaining" +msgstr "Ongeveer %i seconden te gaan" -#: rapid/rapid.py:2529 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Backup van %(file_type)s bestaat reeds" +#: rapid/rapid.py:2134 +msgid "About 1 minute remaining" +msgstr "Ongeveer 1 minuut te gaan" -#: rapid/rapid.py:2533 +#. 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:2139 #, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "Backup van %(file_type)s overschreven" +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Ongeveer %(minutes)i:%(seconds)02i minuten te gaan" -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "%(file_type)s niet gebackuped op %(volume)s" +#: rapid/rapid.py:2151 rapid/preferencesdialog.py:822 rapid/rpdfile.py:110 +msgid "photos and videos" +msgstr "foto's en video's" -#: rapid/rapid.py:2539 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "%(file_type)s niet gebackuped" +#: rapid/rapid.py:2153 rapid/rpdfile.py:112 +msgid "photos or videos" +msgstr "foto's of video's" -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" -msgstr "Backup fout" +#: rapid/rapid.py:2156 rapid/rapid.py:2661 rapid/rpdfile.py:115 +msgid "videos" +msgstr "video's" -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Doelmap kon niet aangemaakt worden: %(directory)s\n" +#: rapid/rapid.py:2158 rapid/preferencesdialog.py:1371 rapid/rpdfile.py:117 +#: rapid/rpdfile.py:266 +msgid "video" +msgstr "video" -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" -msgstr "Fout: %(inst)s" +#: rapid/rapid.py:2161 rapid/rapid.py:2659 rapid/preferencesdialog.py:824 +#: rapid/rpdfile.py:120 +msgid "photos" +msgstr "foto's" -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "De %(file_type)s werd niet gebackuped" +#. check subfolder preferences for bad values +#: rapid/rapid.py:2163 rapid/preferencesdialog.py:1370 rapid/rpdfile.py:122 +#: rapid/rpdfile.py:246 +msgid "photo" +msgstr "foto" -#: rapid/rapid.py:2595 rapid/rapid.py:2645 +#: rapid/rapid.py:2188 #, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Fout: %(errno)s %(strerror)s" +msgid "%(noFiles)s %(filetypes)s downloaded" +msgstr "%(noFiles)s %(filetypes)s gedownload" -#: rapid/rapid.py:2658 +#: rapid/rapid.py:2192 #, python-format -msgid "%(file_type)s could not be backed up" -msgstr "%(file_type)s kon niet gebackuped worden" - -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" -msgstr "Geen geldig backup volume gevonden" +msgid "%(noFiles)s %(filetypes)s failed to download" +msgstr "%(noFiles)s %(filetypes)s kon niet gedownload worden" -#: rapid/rapid.py:2663 -msgid "A backup location was not found" -msgstr "Een backup locatie werd niet gevonden" +#: rapid/rapid.py:2195 rapid/rapid.py:2247 +msgid "warnings" +msgstr "verwittigingen" -#: rapid/rapid.py:2717 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." -msgstr "Dit apparaat heeft geen %(types_searched_for)s om te downloaden" +#: rapid/rapid.py:2204 +msgid "All downloads complete" +msgstr "Alle downloads zijn afgelopen" -#: rapid/rapid.py:2813 +#: rapid/rapid.py:2210 rapid/rapid.py:2219 rapid/rapid.py:2228 +#: rapid/rapid.py:2237 rapid/rapid.py:2245 #, python-format -msgid "Download has started from %s" -msgstr "Download begonnen vanaf %s" +msgid "%(number)s %(numberdownloaded)s" +msgstr "%(number)s %(numberdownloaded)s" -#: rapid/rapid.py:2817 +#: rapid/rapid.py:2212 rapid/rapid.py:2230 #, python-format -msgid "Attempting to download %s files" -msgstr "Proberen om %s bestanden te downloaden" +msgid "%(filetype)s downloaded" +msgstr "%(filetype)s gedownload" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 +#: rapid/rapid.py:2221 rapid/rapid.py:2239 #, python-format -msgid "%(number)s of %(total)s %(filetypes)s" -msgstr "%(number)s van %(total)s %(filetypes)s" +msgid "%(filetype)s failed to download" +msgstr "%(filetype)s werden niet gedownload" -#: rapid/rapid.py:2913 +#. e.g.: 3 of 205 photos and videos (202 remaining) +#: rapid/rapid.py:2276 #, python-format msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" msgstr "" "%(number)s van de %(total)s %(filetypes)s (%(remaining)s blijven over)" -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" -msgstr "Kon foto of video niet verwijderen van apparaat" - -#: rapid/rapid.py:2939 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" -msgstr "" -"Foto: %(source)s\n" -"Fout: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" -msgstr "Foto: %(source)s" - -#: rapid/rapid.py:2945 +#. e.g.: 205 of 205 photos and videos +#: rapid/rapid.py:2283 #, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "Verwijderde %(number)i %(filetypes)s van apparaat" - -#: rapid/rapid.py:2958 -#, python-format -msgid "Download complete from %s" -msgstr "Download van %s afgelopen" - -#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. -#: rapid/rapid.py:3073 rapid/rapid.py:3542 -msgid "Device" -msgstr "Apparaat" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" -msgstr "Grootte" - -#: rapid/rapid.py:3081 -msgid "Download Progress" -msgstr "Downloadvoortgang" - -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" -msgstr "Downloaden van Camera's" - -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" -msgstr "" -"Het rechtstreeks downloaden vanaf een camera kan slecht, tot helemaal niet " -"werken" - -#: rapid/rapid.py:3176 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." -msgstr "" -"Het downloaden van een kaartlezer werkt altijd en is meestal sneller. Het " -"wordt tenstelligste aanbevolen een kaartlezer te gebruiken." - -#: rapid/rapid.py:3190 -msgid "_Show this message again" -msgstr "_Toon dit bericht opnieuw" - -#: rapid/rapid.py:3225 -msgid "Device Detected" -msgstr "Apparaat gedetecteerd" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "" -"Should this device or partition be used to download photos or videos from?" -msgstr "" -"Moet dit apparaat of deze partitie gebruikt worden om foto's of video's van " -"te halen?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 -msgid "_Remember this choice" -msgstr "_Herinner deze keuze" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s aangeduid om gedownload te worden van" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" -msgstr "" -"Dit apparaat of deze partitie zal altijd gebruikt worden om van te downloaden" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s afgewezen als download apparaat" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" -msgstr "" -"Dit apparaat of deze partitie zal nooit gebruikt worden om van te downloaden" - -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" -msgstr "Verwijder alle Job Codes?" - -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" -msgstr "Moeten alle Job Codes verwijderd worden?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" -msgstr "Geef een Job Code op" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" -msgstr "Geef een nieuwe Job Code in of selecteer een bestaande" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" -msgstr "Geef een nieuwe Job Code in" - -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" -msgstr "Job Code:" - -#: rapid/rapid.py:3425 -msgid "Job Code entered" -msgstr "Job Code ingevoerd" - -#: rapid/rapid.py:3427 -msgid "Job Code not entered" -msgstr "Job Code niet ingevoerd" - -#: rapid/rapid.py:3477 -msgid "Status" -msgstr "Status" - -#: rapid/rapid.py:3485 -msgid "Type" -msgstr "Type" - -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" -msgstr "Foto" - -#: rapid/rapid.py:3496 -msgid "File" -msgstr "Bestand" - -#: rapid/rapid.py:3511 -msgid "Job Code" -msgstr "Job Code" - -#: rapid/rapid.py:3521 -msgid "Date" -msgstr "Datum" - -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" -msgstr "Bestandsnaam" - -#: rapid/rapid.py:3564 -msgid "Path" -msgstr "Pad" - -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s was met succes gedownload" - -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s werd niet gedownload" - -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s werd gedownload met opmerkingen" - -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" -msgstr "" -"%(filetype)s werd gedownload maar er waren problemen tijdens het backuppen" - -#: rapid/rapid.py:3982 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "%(filetype)s werd niet gedownload noch gebackupped" +msgid "%(number)s of %(total)s %(filetypes)s" +msgstr "%(number)s van %(total)s %(filetypes)s" -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s is klaar om gedownload te worden" +#: rapid/rapid.py:2665 +msgid "Free space:" +msgstr "Vrije ruimte:" -#: rapid/rapid.py:3986 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2677 #, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "%(filetype)s staat op het punt gedownload te worden" +msgid "(%(file_type)s)" +msgstr "(%(file_type)s)" -#: rapid/rapid.py:3988 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2681 #, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s zal gedownload worden met opmerkingen" +msgid "%(free)s %(file_type)s" +msgstr "%(free)s %(file_type)s" -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s kan niet gedownload worden" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2686 +msgid "; " +msgstr "; " -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "" -"Geef een nieuwe Job Code op en druk op Enter, of selecteer een bestaande Job " -"Code" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2691 +msgid "." +msgstr "." -#: rapid/rapid.py:5034 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2697 #, python-format -msgid "%(free)s available" -msgstr "%(free)s beschikbaar" +msgid "%(free)s free" +msgstr "%(free)s vrij" #. user manually specified backup location -#: rapid/rapid.py:5040 +#: rapid/rapid.py:2703 #, python-format msgid "Backing up to %(path)s" msgstr "Backuppen naar %(path)s" -#: rapid/rapid.py:5045 +#: rapid/rapid.py:2708 #, python-format msgid "%(freespace)s. %(backuppaths)s." msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" -"Sorry, deze apparaat locatie bestaat niet:\n" -"%(path)s\n" -"\n" -"Los het probleem op, of pas de voorkeuren aan." +#: rapid/rapid.py:2737 +msgid "Program preferences are invalid" +msgstr "Programma voorkeuren zijn ongeldig" -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" -msgstr "Probleem met de Apparaat Locatie Map" +#: rapid/rapid.py:2842 rapid/rpdfile.py:247 +msgid "Photo" +msgstr "Foto" -#: rapid/rapid.py:5067 +#: rapid/rapid.py:2844 rapid/rpdfile.py:267 msgid "Video" msgstr "Video" -#: rapid/rapid.py:5074 +#: rapid/rapid.py:2853 #, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "De %(file_type)s Download Map bestaat niet\n" +msgid "%(file_type)s download folder does not exist" +msgstr "%(file_type)s downloadmap bestaat niet" -#: rapid/rapid.py:5083 +#: rapid/rapid.py:2855 rapid/rapid.py:2869 rapid/rapid.py:2882 #, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "De %(file_type)s Download Map bestaat maar is niet beschrijfbaar.\n" - -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" -"Sorry, er waren problemen met je download mappen. Los deze problemen op of " -"pas de voorkeuren aan.\n" -"\n" - -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" -msgstr "Probleem met de Download Map" - -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" -msgstr "Prbleem met de Download Mappen" - -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." -msgstr "Sommige voorkeuren worden gereset" +msgid "Folder: %s" +msgstr "Map: %s" -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" -msgstr "" -"Opmerking vertonen betreffende het rechtstreeks downloaden vanaf een camera" - -#: rapid/rapid.py:5149 +#: rapid/rapid.py:2867 #, python-format -msgid "Prompting whether to use %s" -msgstr "Vragen om %s te gebruiken" - -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" -msgstr "Vragen naar de Job Code" - -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Reeds bezig met vragen naar Job Code, vraag niet opnieuw" - -#: rapid/rapid.py:5197 -msgid "Starting downloads" -msgstr "Downloaden aanvangen" - -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "Downloads beginnen die op een Job Code aan het wachten waren" - -#: rapid/rapid.py:5248 -#, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "Foto download map %(folder)s wordt aangemaakt" - -#: rapid/rapid.py:5253 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "Kon de standaard foto download map %(folder)s niet aanmaken" - -#: rapid/rapid.py:5257 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "Video download map %(folder)s wordt aangemaakt" - -#: rapid/rapid.py:5262 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "Kon de standaard video download map %(folder)s niet aanmaken" - -#: rapid/rapid.py:5287 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" -msgstr "" -"Een recentere versie van dit programma werd reeds op deze computer " -"opgestart.\n" -"\n" - -#: rapid/rapid.py:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"Programma voorkeuren blijken OK te zijn, maar controleer toch even op " -"correcte werking van het programma" - -#: rapid/rapid.py:5291 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "Sorry, bepaalde voorkeuren zijn ongeldig en worden gereset." - -#: rapid/rapid.py:5292 -msgid "Warning:" -msgstr "Waarschuwing:" - -#: rapid/rapid.py:5297 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." -msgstr "" -"Deze versie van het programma is recenter dan de vorige. De voorkeuren " -"worden overlopen." - -#: rapid/rapid.py:5304 -msgid "Preferences were modified." -msgstr "Voorkeuren werden aangepast." - -#: rapid/rapid.py:5305 -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 "" -"Deze versie van het programma gebruikt andere voorkeuren dan de vorige " -"versie. Uw voorkeuren werden aangepast.\n" -"\n" -"Gelieve deze te controleren om een goede werking te garanderen." - -#: rapid/rapid.py:5309 -msgid "No preferences needed to be changed." -msgstr "Er dienen geen voorkeuren aangepast te worden." - -#: rapid/rapid.py:5311 -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 "" -"Deze versie van het programma gebruikt andere voorkeuren dan de vorige. " -"Bepaalde van je vorige voorkeuren zijn ongeldig en kunnen niet aangepast " -"worden. Ze worden naar standaard waarden teruggebracht." - -#: rapid/rapid.py:5321 -msgid "Problem using pynotify." -msgstr "Probleem met het gebruik van pynotify." - -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." -msgstr "Kon de pynotify server mogelijkheden niet ontvangen." - -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Opgelet: de desktop environment notification server is verkeerd ingesteld." - -#: rapid/rapid.py:5396 -msgid "and" -msgstr "en" - -#: rapid/rapid.py:5401 -msgid "Using backup devices" -msgstr "Backup apparaten aan het gebruiken" - -#: rapid/rapid.py:5403 -msgid "Using backup device" -msgstr "Backup apparaat aan het gebruiken" - -#: rapid/rapid.py:5405 -msgid "No backup devices detected" -msgstr "Geen backup apparaat gedetecteerd" +msgid "%(file_type)s download folder is invalid" +msgstr "%(file_type)s downloadmap is ongeldig" -#: rapid/rapid.py:5455 rapid/rapid.py:5617 +#: rapid/rapid.py:2880 #, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Apparaat %(device)s (%(path)s) wordt genegeerd" +msgid "%(file_type)s download folder is not writable" +msgstr "%(file_type)s downloadmap is niet beschrijfbaar" -#: rapid/rapid.py:5576 -#, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Detecteerde %(device)s met als pad %(path)s" - -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" -msgstr "Automatisch opstarten download is waar" - -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" -msgstr "Automatisch opstarten download is onwaar" - -#: rapid/rapid.py:5635 -msgid "Using manually specified path" -msgstr "Manueel ingegeven pad aan het gebruiken" - -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" -msgstr "" -"Opmerking: er wordt momenteel gedownload vanaf backup apparaat %(device)s" - -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" -msgstr "D_ownload geselecteerd" - -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" -msgstr "Alle downloads zijn afgelopen" - -#: rapid/rapid.py:5837 -msgid "MB/s" -msgstr "MB/s" - -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" -msgstr "Ongeveer 1 seconde te gaan" - -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" -msgstr "Ongeveer %i seconden te gaan" - -#: rapid/rapid.py:5851 -msgid "About 1 minute remaining" -msgstr "Ongeveer 1 minuut te gaan" - -#. 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:5856 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Ongeveer %(minutes)i:%(seconds)02i minuten te gaan" - -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" - -#: rapid/rapid.py:5878 rapid/rapid.py:5890 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s gedownload" - -#: rapid/rapid.py:5884 rapid/rapid.py:5896 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "%(filetype)s werden niet gedownload" - -#: rapid/rapid.py:6070 -msgid "_Resume" -msgstr "_Hervatten" - -#: rapid/rapid.py:6073 -msgid "_Download All" -msgstr "_Alles Downloaden" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" -msgstr "_Pauze" - -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." -msgstr "De download apparaat instellingen zijn veranderd" - -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." -msgstr "Backup voorkeuren zijn veranderd." - -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." -msgstr "Subfolder en bestandsnaam voorkeuren zijn veranderd." - -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." -msgstr "Downloadmap voorkeuren zijn veranderd." - -#: rapid/rapid.py:6422 -msgid "Goodbye" -msgstr "Tot later" +#: rapid/rapid.py:2958 +msgid "Thumbnails" +msgstr "Miniaturen" #. 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:6433 +#: rapid/rapid.py:3005 #, python-format msgid "" "display program information on the command line as the program runs " @@ -1093,578 +297,1216 @@ msgstr "" "vertoon programma informatie op de commando lijn wanneer het programma " "draait (standaard: %default)" -#: rapid/rapid.py:6434 +#: rapid/rapid.py:3006 msgid "display debugging information when run from the command line" msgstr "vertoon debug informatie wanneer uitgevoerd vanop de commando prompt" -#: rapid/rapid.py:6435 +#: rapid/rapid.py:3007 msgid "only output errors to the command line" msgstr "alleen fouten naar de commandolijn sturen" #. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6437 +#: rapid/rapid.py:3009 msgid "list photo and video file extensions the program recognizes and exit" msgstr "" "vertoon de foto en video bestandsextenties welke het programma herkent en " "verlaat het programma" -#: rapid/rapid.py:6438 +#: rapid/rapid.py:3010 msgid "reset all program settings and preferences and exit" msgstr "reset alle programma instellingen en verlaat het programma" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:3023 msgid "Photos:" msgstr "Foto's:" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:3023 msgid "Videos:" msgstr "Video's:" -#: rapid/rapid.py:6457 +#: rapid/rapid.py:3028 #, python-format msgid "and %s" msgstr "en %s" -#: rapid/rapid.py:6465 +#: rapid/rapid.py:3036 msgid "All settings and preferences have been reset" msgstr "Alle instellingen en voorkeuren werden gereset" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" -msgstr "Gebruik makend van" - -#: rapid/rapid.py:6474 -msgid "\n" -msgstr "\n" +#: rapid/rapid.py:3045 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." +msgstr "" +"Video download functie uitgezet.\n" +"Om video's te downloaden moet u de hachoir metadata en de kaa metadata " +"pakketten voor python installeren." -#. this application is already running -#: rapid/rapid.py:6498 +#: rapid/copyfiles.py:142 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:332 rapid/subfolderfile.py:350 #, python-format -msgid "%s is already running" -msgstr "%s is al draaiende" +msgid "" +"%(problem)s\n" +"File: %(file)s" +msgstr "" +"%(problem)s\n" +"Bestand: %(file)s" -#: rapid/renamesubfolderprefs.py:192 +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Apparaat gedetecteerd" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "" +"Moet dit apparaat of deze partitie gebruikt worden om foto's of video's van " +"te halen?" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "_Herinner deze keuze" + +#: rapid/downloadtracker.py:217 +msgid "MB/s" +msgstr "MB/s" + +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Datum/tijd" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Tekst" -#: rapid/renamesubfolderprefs.py:195 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Bestandsnaam" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Metadata" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Reeksen" -#: rapid/renamesubfolderprefs.py:199 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:549 +msgid "Job code" +msgstr "Job code" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Afbeeldingsgegevens" -#: rapid/renamesubfolderprefs.py:200 +#: rapid/generatenameconfig.py:151 msgid "Video date" msgstr "Video datum" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Vandaag" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Gisteren" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 +#: rapid/generatenameconfig.py:155 msgid "Download time" msgstr "Download tijd" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 +#: rapid/generatenameconfig.py:157 msgid "Name + extension" msgstr "Naam + extentie" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:208 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Naam" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 +#: rapid/generatenameconfig.py:161 msgid "Extension" msgstr "Extentie" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Afbeelding nummer" -#: rapid/renamesubfolderprefs.py:213 +#: rapid/generatenameconfig.py:164 msgid "Video number" msgstr "Video nummer" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Diafragma" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 +#: rapid/generatenameconfig.py:168 msgid "ISO" msgstr "ISO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:219 +#: rapid/generatenameconfig.py:170 msgid "Exposure time" msgstr "Belichtingstijd" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:221 +#: rapid/generatenameconfig.py:172 msgid "Focal length" msgstr "Brandpuntsafstand" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:223 +#: rapid/generatenameconfig.py:174 msgid "Camera make" msgstr "Camera merk" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:225 +#: rapid/generatenameconfig.py:176 msgid "Camera model" msgstr "Camera model" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:227 +#: rapid/generatenameconfig.py:178 msgid "Short camera model" msgstr "Camera model (kort)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:229 +#: rapid/generatenameconfig.py:180 msgid "Hyphenated short camera model" msgstr "Camera model (kort na koppelteken)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:231 +#: rapid/generatenameconfig.py:182 msgid "Serial number" msgstr "Serienummer" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:233 +#: rapid/generatenameconfig.py:184 msgid "Shutter count" msgstr "Sluiter teller" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:235 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Naam eigenaar" -#: rapid/renamesubfolderprefs.py:236 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Codec" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Breedte" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Hoogte" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Lengte" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Frames per seconde" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 +#: rapid/generatenameconfig.py:193 msgid "Downloads today" msgstr "Downloads vandaag" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:244 +#: rapid/generatenameconfig.py:195 msgid "Session number" msgstr "Sessienummer" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:246 +#: rapid/generatenameconfig.py:197 msgid "Subfolder number" msgstr "Nummer Submap" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:248 +#: rapid/generatenameconfig.py:199 msgid "Stored number" msgstr "Opgeslagen nummer" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:250 +#: rapid/generatenameconfig.py:201 msgid "Sequence letter" msgstr "Vervolg letter" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:252 +#: rapid/generatenameconfig.py:203 msgid "All digits" msgstr "Alle cijfers" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:254 +#: rapid/generatenameconfig.py:205 msgid "Last digit" msgstr "Laatste cijfer" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:256 +#: rapid/generatenameconfig.py:207 msgid "Last 2 digits" msgstr "Laatste 2 cijfers" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:258 +#: rapid/generatenameconfig.py:209 msgid "Last 3 digits" msgstr "Laatste 3 cijfers" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:260 +#: rapid/generatenameconfig.py:211 msgid "Last 4 digits" msgstr "Laatste 4 cijfers" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:262 +#: rapid/generatenameconfig.py:213 msgid "Original Case" msgstr "Oorspronkelijke hoofdletterstatus" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:264 +#: rapid/generatenameconfig.py:215 msgid "UPPERCASE" msgstr "HOOFDLETTERS" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "kleine letters" -#: rapid/renamesubfolderprefs.py:267 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Eén cijfer" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Twee cijfers" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Drie cijfers" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Vier cijfers" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Vijf cijfers" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Zes cijfers" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "Zeven cijfers" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 +#: rapid/generatenameconfig.py:226 msgid "Subseconds" msgstr "Subseconden" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "JJJJMMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 +#: rapid/generatenameconfig.py:230 msgid "YYYY-MM-DD" msgstr "JJJJ-MM-DD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:281 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "JJMMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 +#: rapid/generatenameconfig.py:234 msgid "YY-MM-DD" msgstr "JJ-MM-DD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:285 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "MMDDJJJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "MMDDJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "MMDD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "DDMMJJJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "DDMMJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "JJJJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "JJ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "DD" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "HHMMSS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "HHMM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "HH-MM-SS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "HH-MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "HH" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "MM (minuten)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "SS" -#: rapid/renamesubfolderprefs.py:800 +#: rapid/preferencesdialog.py:370 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Submap voorkeuren mogen niet starten met een %s" + +#: rapid/preferencesdialog.py:372 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Submap voorkeuren mogen niet eindigen op een %s" + +#: rapid/preferencesdialog.py:376 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "Submap voorkeuren mogen geen twee opeenvolgende %s bevatten" + +#: rapid/preferencesdialog.py:389 rapid/preferencesdialog.py:672 +msgid "Remove all Job Codes?" +msgstr "Verwijder alle Job Codes?" + +#: rapid/preferencesdialog.py:406 rapid/preferencesdialog.py:689 +msgid "Should all Job Codes be removed?" +msgstr "Moeten alle Job Codes verwijderd worden?" + +#: rapid/preferencesdialog.py:436 +msgid "Error in Photo Rename preferences" +msgstr "Fout in de voorkeuren van Foto Hernoemen" + +#: rapid/preferencesdialog.py:617 +msgid "Error in Video Rename preferences" +msgstr "Fout in de voorkeuren Video Hernoemen" + +#: rapid/preferencesdialog.py:638 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Fout in de voorkeuren van Photo Download Subfolders" + +#: rapid/preferencesdialog.py:655 +msgid "Error in Video Download Subfolders preferences" +msgstr "Fout in de voorkeuren Video Download Subfolders" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:714 +msgid "Enter a Job Code" +msgstr "Geef een Job Code op" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:731 +msgid "Enter a new Job Code, or select a previous one" +msgstr "Geef een nieuwe Job Code in of selecteer een bestaande" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:734 +msgid "Enter a new Job Code" +msgstr "Geef een nieuwe Job Code in" + +#: rapid/preferencesdialog.py:739 +msgid "Job Code:" +msgstr "Job Code:" + +#: rapid/preferencesdialog.py:915 +msgid "Job Code" +msgstr "Job Code" + +#: rapid/preferencesdialog.py:997 +msgid "Select a folder to download photos to" +msgstr "Duid een map aan om de foto's naar toe te downloaden" + +#: rapid/preferencesdialog.py:1015 +msgid "Select a folder to download videos to" +msgstr "Selecteer een folder om de video's naar toe te downloaden" + +#: rapid/preferencesdialog.py:1106 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Selecteer een map die %(file_types)s bevat" + +#: rapid/preferencesdialog.py:1128 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "" +"Selecteer een map waar %(file_types)s naar toe gebackuped moeten worden" + +#. 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/preferencesdialog.py:1212 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Opgepast:</b> Er is onvoldoende metadata om een volledige naam aan te " +"maken. Gelieve andere hernoemings opties te gebruiken.</i>" + +#: rapid/preferencesdialog.py:1263 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Opgepast:</b> Er is onvoldoende metadata om volledige subfolders aan " +"te maken. Kies andere subfolder benoemings opties.</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/preferencesdialog.py:1266 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Voorbeeld: %s</i>" + +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1356 #, python-format msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." msgstr "" -"Voorkeurtoets '%(key)s' is ongeldig.\n" -"Eén van %(value)s werd verwacht" +"De voorkeuren voor de %(filetype)s subfolder zijn ongeldig en kunnen niet " +"gebruikt worden.\n" +"Ze zullen naar de standaard waardes worden teruggezet." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1642 +msgid "externaldrive1" +msgstr "extern apparaat 1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1644 +msgid "externaldrive2" +msgstr "extern apparaat 2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "New York" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manilla" + +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Praag" -#: rapid/renamesubfolderprefs.py:807 +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinki" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Teheran" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Parijs" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlijn" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sydney" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Boedapest" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Rome" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moskou" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Delhi" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Warschau" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jakarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madrid" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Stockholm" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:343 +msgid "subfolder" +msgstr "subfolder" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:341 +msgid "filename" +msgstr "bestandsnaam" + +#: rapid/problemnotification.py:80 #, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "Voorkeurwaarde '%(value)s' is ongeldig" +msgid "Date time value %s appears invalid." +msgstr "Datum / tijd waarde %s blijkt ongeldig te zijn." -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" -msgstr "Deze voorkeuren zijn niet goed opgesteld:" +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "Bestandsnaam heeft geen extentie." -#: rapid/renamesubfolderprefs.py:1524 +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "Bestandsnaam bevat geen getallenreeks." + +#: rapid/problemnotification.py:84 #, python-format -msgid "Subfolder preferences should not start with a %s" -msgstr "Submap voorkeuren mogen niet starten met een %s" +msgid "Error generating component %s." +msgstr "Fout bij het aanmaken van component %s." -#: rapid/renamesubfolderprefs.py:1526 +#. a generic problem +#: rapid/problemnotification.py:86 #, python-format -msgid "Subfolder preferences should not end with a %s" -msgstr "Submap voorkeuren mogen niet eindigen op een %s" +msgid "%(filetype)s metadata cannot be read" +msgstr "%(filetype)s metadata kan niet gelezen worden" -#: rapid/renamesubfolderprefs.py:1530 +#: rapid/problemnotification.py:88 #, python-format -msgid "Subfolder preferences should not contain two %s one after the other" -msgstr "Submap voorkeuren mogen geen twee opeenvolgende %s bevatten" +msgid "%(filetype)s %(area)s could not be generated" +msgstr "%(filetype)s %(area)s kon niet aangemaakt worden" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "Er is een fout gebeurd tijdens het kopiëren van de %(filetype)s" + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "%(filetype)s bestaat reeds" + +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." +msgstr "" +"%(filetype)s konden niet gebackupped worden omdat er geen gepaste backup " +"plaats gevonden werd." + +#: rapid/problemnotification.py:102 +#, python-format +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." +msgstr "" +"%(image1)s werd genomen op %(image1_date)s om %(image1_time)s en %(image2)s " +"op %(image2_date)s om %(image2_time)s." + +#: rapid/problemnotification.py:103 +#, python-format +msgid "%(filetype)s was already downloaded" +msgstr "%(filetype)s werd eerder al gebackupped" + +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." +msgstr "" +"De bestaande %(filetype)s werd laatst aangepast op %(date)s om %(time)s. " +"Uniek identificatienummer '%(identifier)s' toegevoegd." + +#: rapid/problemnotification.py:108 +#, python-format +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "" +"De bestaande %(filetype)s werd laatst aangepast op %(date)s om %(time)s." + +#: rapid/problemnotification.py:109 +#, python-format +msgid "There is no data with which to name the %(filetype)s." +msgstr "Er zijn geen gegevens om de %(filetype)s een naam te geven." + +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" +msgstr "Fout: %(errorno)s %(strerror)s" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "De metadata kan foutief zijn." + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "" +"De bestandsnaam, extentie en Exif informatie geven aan dat het reeds " +"gedownload werd." + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr " Het werd gebackupped naar %(volume)s" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr " Het werd gebackupped naar deze apparaten: " + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "%s, " + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "%(volumes)s en %(final_volume)s." + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" +"Afbeeldingen ontdekt met dezelfde bestandsnamen maar genomen op " +"verschillende tijden: %(details)s" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "Een fout gebeurde tijdens het backuppen naar %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "Een fout gebeurde tijdens het backuppen naar %(volume)s." + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "Fouten gebeurden tijdens het backuppen naar de volgende apparaten: " + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "%(volume)s (%(inst)s), " + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "%(volume)s, " + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "%(volumes)s en %(volume)s (%(inst)s)." + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "%(volumes)s en %(volume)s." + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "Backup bestaat reeds op %(volume)s." -#: rapid/glade3/rapid.glade.h:1 +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "Backups bestaan reeds op volgende plaatsen: " + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "Backup overschreven op %(volume)s." + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "Backups overschreven op deze apparaten: " + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "" +"Een fout gebeurde tijdens het aanmaken van mappen op %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "" +"Fouten gebeurden tijdens het aanmaken van mappen op de volgende backup " +"apparaten: " + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "%(previousproblem)s Daarbovenop, %(newproblem)s" + +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr " Daarenboven waren er %(problems)s." + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr " Daarenboven was er een %(problem)s." + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "De %(type)s metadata ontbreekt." + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "De volgende metadata ontbreekt: " + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "%(missing_metadata_elements)s en %(final_missing_metadata_element)s." + +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "Problemen bij het aanmaken van de submappen en bestandsnamen" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "Probleen bij het aanmaken van de submappen en bestandsnamen" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "Problemen bij het aanmaken van %s" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "Probleen bij het aanmaken van %s" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "%(filetype)s bestaat reeds, maar het was gebackupped" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "" +"Een fout gebeurde bij het kopiëren van %(filetype)s, maar het was gebackupped" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "Meerdere problemen tegengekomen" + +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "" +"Foto's gevonden met dezelfde bestandsnaam, maar op een verschillend tijdstip " +"genomen" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "er waren fouten tijdens het backuppen" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "Er waren fouten tijdens het backuppen" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "er was een fout tijdens het backuppen" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "Er was een fout tijdens het backuppen" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "%(previousproblem)s, en %(backinguperror)s" + +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" + +#: rapid/subfolderfile.py:194 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Bron: %(source)s\n" +"Doel: %(destination)s" + +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" +msgstr "Foto werd al eens gedownload" + +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" +msgstr "Bron: %(source)s" + +#: rapid/subfolderfile.py:339 +msgid "subfolder and filename" +msgstr "subfolder en bestandsnaam" + +#: rapid/subfolderfile.py:377 +msgid "Failed to create download subfolder" +msgstr "Kon downloadmap niet aanmaken" + +#: rapid/subfolderfile.py:378 +#, python-format +msgid "Path: %s" +msgstr "Pad: %s" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "Over..." + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "Alles aanvinken" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "Alle Foto's Aanvinken" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "Alle Video's Aanvinken" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Download / Pauze" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "Online hulp verkrijgen..." + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "Doe een Gift..." + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "Volgend Bestand" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "Vorig Bestand" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "Afsluiten" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "Vernieuwen" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "Een probleem melden..." + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "Selecteer Alle _met Job Code" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "Selecteer Alle Zonder _Job Code" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "Vertaal deze Toepassing..." + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "Alles deselecteren" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "Alles _aanvinken" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Verwijder Afgewerkte Downloads" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" +msgstr "_Downloaden" + +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "_Fouten log" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Bestand" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "_Help" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "_In download meenemen" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Doe een gift..." + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Selecteer" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Vertaal deze Toepassing" + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" +msgstr "Alles _uitvinken" + +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "_Weergave" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " hh:mm" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "<b>Backup</b>" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Compatibiliteit met andere besturingssystemen</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "<b>Apparaten</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Download Map</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Download Submappen</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Voorbeeld</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Job Codes</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "<b>Foto Hernoemen</b>" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "<b>Foto- en Videonaam conflict</b>" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Programma Automatisatie</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Volgnummers</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/media/externaldrive/Photos</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Voorbeeld: /home/user/Afbeeldingen</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Voorbeeld:</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Nieuw:</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 msgid "<i>Original:</i>" msgstr "<i>Origineel:</i>" -#: rapid/glade3/rapid.glade.h:21 -msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" -msgstr "<span weight=\"bold\" size=\"x-large\">Automatisatie</span>" - -#: rapid/glade3/rapid.glade.h:22 +#: rapid/glade3/prefs.ui.h:20 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 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Apparaten</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Foutverwerking</span>" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "<span weight=\"bold\" size=\"x-large\">Diversen</span>" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Photo Download Mappen</span>" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Foto Hernoemen</span>\t" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.h:27 msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Hernoemingsopties</span>" -#: rapid/glade3/rapid.glade.h:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Video Download Mappen</span>" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Video Hernoemen</span>\t" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Unieke identifier toevoegen" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Automatisch detecteren van Draagbare Opslagmedia" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Automatisch detecteren van backup apparaten" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Automatisch apparaten ontdekken" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Automatisering" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Backup" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Backup locatie:" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "Backup foto's en video's gedurende het downloaden" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1672,7 +1514,7 @@ msgstr "" "Kies de downloadmap. Submappen voor de gedownloadde foto's zullen " "automatisch aangemaakt worden in deze map volgens de structuur hieronder." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." @@ -1680,24 +1522,20 @@ msgstr "" "Kies de download map. Submappen voor de gedownloadde video's zullen " "automatisch aangemaakt worden in deze map conform de onderstaande structuur." -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Copyright Damon Lynch 2007-10" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Aanvang dag:" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" "Verwijder foto's en video's van het apparaat als de download afgelopen is" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Apparaten" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1719,38 +1557,32 @@ msgstr "" "helemaal niet gaat, probeer dan eens de instelling naar PTP mode te zetten. " "Als dat niet kan, zoek dan je heil in een kaartlezer..</i>" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Download / Pauze" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Download map:" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Downloads vandaag:" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Foutafhandeling" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Foutenlog" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" +msgstr "Beëindig programma zelfs indien de download fouten of meldingen had" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" -msgstr "" -"Verlaat het programma als de download zonder verwittigingen noch fouten " -"beëindigd wordt." +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" +msgstr "Beëindig programma als de download afgelopen is" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" "Als je de automatische herkenning uitschakelt, kies de juiste backup plaats." -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." @@ -1758,7 +1590,7 @@ msgstr "" "Als je de automatische detectie afzet, kies dan de juiste plaats van de " "beelden en video's." -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1768,118 +1600,55 @@ msgstr "" "het volledig apparaat gescanned worden op afbeeldingen. Bij grote apparaten, " "kan dat een tijd duren." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "Importeer je foto's en video's efficiënt en betrouwbaar" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Job Codes" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Locatie:" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "Diversen" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Overschrijven" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "P_review Kolommen" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "Foto Mappen" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "Foto Hernoemen" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "Foto backup foldernaam:" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Voorkeuren: Rapid Photo Downloader" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "Preview _Mappen" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "V_erwijder alles" -#: rapid/glade3/rapid.glade.h:72 -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 vrije software; je mag het herverdelen en/of " -"aanpassen onder de termen van de GNU General Public License zoals " -"gepubliceerd door de Free Software Foundation; ofwel versie 2 van de " -"License, of (volgens jou voorkeur) elke latere versie.\n" -"\n" -"Rapid Photo Downloader wordt verdeeld in de hoop dat het nuttig zal zijn, " -"maar ZONDER ENIGE GARANTIE; zelfs zonder de impliciete garantie van " -"VERKOOPBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL . Zie de GNU General " -"Public License voor meer details.\n" -"\n" -"Je zou een kopie van de GNU General Public License ontvangen moeten hebben " -"samen met Rapid Photo Downloader; indien niet, contacteer de Free Software " -"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, " -"USA." - -#: rapid/glade3/rapid.glade.h:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Hernoemingsopties" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "Se_lecteer Geen Enkele" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Selecteer Alle Fo_to's" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Selecteer Alle Vi_deo's" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "Selecteer Alle _met Job Code" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "Selecteer Alle Zonder _Job Code" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "Selecteer _Alles" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Overslaan" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Download overslaan" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " @@ -1889,7 +1658,7 @@ msgstr "" "<i>hachoir metadata</i> en <i>kaa metadata</i> pakketten voor python " "installeren." -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1903,7 +1672,7 @@ msgstr "" "niet voor backups gebruikt wordt. Voor ieder apparaat dat je als backup " "wenst te gebruiken, maak er een map in met één van de volgende namen.</i>" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1911,7 +1680,7 @@ msgstr "" "Specifieer de tijd in 24-uurs formaat waar het <i>Downloads vandaag</i> " "volgnummer aan gelijk gezet moet worden.." -#: rapid/glade3/rapid.glade.h:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." @@ -1919,43 +1688,43 @@ msgstr "" "Duid aan of foto-, video- en mapnamen tekens die niet toegelaten zijn bij " "andere besturingssystemen dienen verwijderd te worden." -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Start de download tijdens het opstarten van het programma" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" msgstr "Start de download zodra het apparaat wordt aangekoppeld" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Opgeslagen nummer:" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Verwijder niet-compatibele karakters" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Synchroniseer RAW + JPEG volgnummers" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" msgstr "Ontkoppen (\"eject\") apparaat na beëindigen van de download" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Video Mappen" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" msgstr "Video Hernoemen" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" msgstr "Video backup foldernaam:" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." @@ -1964,7 +1733,7 @@ msgstr "" "om het downloaden van dit bestand over te slaan of om er een uniek " "identificatieteken aan toe te voegen." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." @@ -1972,7 +1741,7 @@ msgstr "" "Kies om het bestand op het backupapparaat met dezelfde naam te " "overschrijven, of over te slaan, gedurende de backup." -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." @@ -1980,81 +1749,44 @@ msgstr "" "Je kan je foto's en video's naar meerdere lokaties backuppen terwijl ze " "gedownload worden, bv. externe harde schijven." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Toevoegen…" -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Verwijder Afgewerkte Downloads" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Apparaat" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "_Fouten log" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Bestand" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "_Bestandsnaam" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Online Help..." - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "_Help" - -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Doe een gift..." - -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Pad" - -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "_Voorbeeld" - -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Rapporteer een probleem..." - -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Selecteer" - -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "_Grootte" - -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Vertaal deze Toepassing" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Importeer je foto's en video's efficiënt en betrouwbaar" -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Type" +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Sorry, deze voorkeuren bevatten een fout:\n" -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "_Weergave" +#~ msgid "Resetting to default values." +#~ msgstr "Terugzetten naar de standaard waardes." #~ msgid "Select a folder in which to backup images" #~ msgstr "Duid een map aan om afbeeldingen naar toe te backuppen" +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Gelieve de voorkeuren te controleren, het programma te herstarten en opnieuw " +#~ "te proberen." + +#~ msgid "There is an error in the program preferences." +#~ msgstr "Er is een fout in de programma voorkeuren." + #, python-format #~ msgid "0 of %s images copied" #~ msgstr "0 van %s afbeeldingen gekopieerd" +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "'Start of day' voorkeurswaarde is corrupt.\n" + +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Terugzetten op middernacht.\n" + #, python-format #~ msgid "Device scan complete: found %(number)s images on %(device)s" #~ msgstr "" @@ -2125,6 +1857,9 @@ msgstr "_Weergave" #~ msgid "Backup image already exists" #~ msgstr "Backup afbeelding bestaat al" +#~ msgid "Backing up error" +#~ msgstr "Backup fout" + #, python-format #~ msgid "" #~ "Destination directory could not be created\n" @@ -2145,6 +1880,9 @@ msgstr "_Weergave" #~ "Doel: %(destination)s\n" #~ "Fout: %(errno)s %(strerror)s" +#~ msgid "The device can now be safely removed" +#~ msgstr "Het apparaat kan nu veilig verwijderd worden" + #, python-format #~ msgid "%s images downloaded" #~ msgstr "%s afbeeldingen gedownload" @@ -2153,9 +1891,16 @@ msgstr "_Weergave" #~ msgid "%s images skipped" #~ msgstr "%s afbeeldingen overgeslaan" +#~ msgid "errors" +#~ msgstr "fouten" + #~ msgid "Backup device missing" #~ msgstr "Backup apparaat afwezig" +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Download begonnen vanaf %s" + #~ msgid "Image skipped" #~ msgstr "Afbeelding overgeslaan" @@ -2193,12 +1938,131 @@ msgstr "_Weergave" #~ msgid "It may be corrupted" #~ msgstr "Het kan corrupt zijn" +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s aangeduid om gedownload te worden van" + +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "" +#~ "Dit apparaat of deze partitie zal altijd gebruikt worden om van te downloaden" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s afgewezen als download apparaat" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "" +#~ "Dit apparaat of deze partitie zal nooit gebruikt worden om van te downloaden" + #~ msgid "Enter a new job code." #~ msgstr "Geef een nieuwe job code." +#~ msgid "Job Code entered" +#~ msgstr "Job Code ingevoerd" + +#~ msgid "Job Code not entered" +#~ msgstr "Job Code niet ingevoerd" + +#~ msgid "Some preferences will be reset." +#~ msgstr "Sommige voorkeuren worden gereset" + +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Vragen om %s te gebruiken" + +#~ msgid "Prompting for Job Code" +#~ msgstr "Vragen naar de Job Code" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Reeds bezig met vragen naar Job Code, vraag niet opnieuw" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "Downloads beginnen die op een Job Code aan het wachten waren" + +#~ msgid "" +#~ "A newer version of this program was previously run on this computer.\n" +#~ "\n" +#~ msgstr "" +#~ "Een recentere versie van dit programma werd reeds op deze computer " +#~ "opgestart.\n" +#~ "\n" + +#~ msgid " " +#~ msgstr " " + +#~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "Programma voorkeuren blijken OK te zijn, maar controleer toch even op " +#~ "correcte werking van het programma" + +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "Sorry, bepaalde voorkeuren zijn ongeldig en worden gereset." + +#~ msgid "Preferences were modified." +#~ msgstr "Voorkeuren werden aangepast." + +#~ 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 "" +#~ "Deze versie van het programma gebruikt andere voorkeuren dan de vorige " +#~ "versie. Uw voorkeuren werden aangepast.\n" +#~ "\n" +#~ "Gelieve deze te controleren om een goede werking te garanderen." + +#~ msgid "No preferences needed to be changed." +#~ msgstr "Er dienen geen voorkeuren aangepast te worden." + +#~ msgid "Problem using pynotify." +#~ msgstr "Probleem met het gebruik van pynotify." + +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Kon de pynotify server mogelijkheden niet ontvangen." + +#~ msgid "and" +#~ msgstr "en" + +#~ msgid "No backup devices detected" +#~ msgstr "Geen backup apparaat gedetecteerd" + +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Apparaat %(device)s (%(path)s) wordt genegeerd" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Detecteerde %(device)s met als pad %(path)s" + +#~ msgid "Automatically start download is true" +#~ msgstr "Automatisch opstarten download is waar" + +#~ msgid "Automatically start download is false" +#~ msgstr "Automatisch opstarten download is onwaar" + #~ msgid "_Download " #~ msgstr "_Download " +#~ msgid "Goodbye" +#~ msgstr "Tot later" + +#~ msgid "Using" +#~ msgstr "Gebruik makend van" + +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s is al draaiende" + +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "Voorkeurwaarde '%(value)s' is ongeldig" + +#~ msgid "_Pause" +#~ msgstr "_Pauze" + #, python-format #~ msgid "Error in date time component. Value %s appears invalid" #~ msgstr "Fout in datum/tijd component. Waarde %s blijkt ongeldig" @@ -2219,6 +2083,12 @@ msgstr "_Weergave" #~ msgid "<i>Example: /home/user/photos</i>" #~ msgstr "<i>Voorbeeld: /home/user/photos</i>" +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "<span weight=\"bold\" size=\"x-large\">Automatisatie</span>" + +#~ msgid "Automation" +#~ msgstr "Automatisering" + #~ msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t" #~ msgstr "<span weight=\"bold\" size=\"x-large\">Afbeelding Hernoemen</span>\t" @@ -2243,6 +2113,9 @@ msgstr "_Weergave" #~ "Als je de automatische herkenning uitschakelt, kies de juiste plaats voor de " #~ "afbeeldingen." +#~ msgid "Error Log" +#~ msgstr "Foutenlog" + #~ msgid "Import your images efficiently and reliably" #~ msgstr "Importeer je afbeeldingen efficiënt en betrouwbaar" @@ -2275,9 +2148,15 @@ msgstr "_Weergave" #~ "Je kan je foto's op meerdere plaatsen backuppen tijdens het downloaden, bv. " #~ "externe harde schijven." +#~ msgid "_Get Help Online..." +#~ msgstr "_Online Help..." + #~ msgid "Start downloading upon image device insertion" #~ msgstr "Start de download zodra het afbeeldingsapparaat aangekoppeld wordt" +#~ msgid "_Report a Problem..." +#~ msgstr "_Rapporteer een probleem..." + #~ msgid "_Photos" #~ msgstr "_Foto's" @@ -2316,6 +2195,12 @@ msgstr "_Weergave" #~ "Kies tijdens het backuppen om een afbeelding met dezelfde naam op het " #~ "backupapparaat te overschrijven of over te slaan." +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Ongeldige Downloads Vandaag waarde.\n" + +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Waarde op nul terugzetten.\n" + #~ msgid "Error in Image Rename preferences" #~ msgstr "Fout in Afbeelding Hernoemen voorkeuren" @@ -2358,6 +2243,10 @@ msgstr "_Weergave" #~ "Metadata is essentieel om submappen / afbeeldingsnamen aan te maken.\n" #~ "Bron: %s" +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "" +#~ "Nieuwe dag begonnen - volgnummer 'Downloads Vandaag' aan het terugzetten" + #~ msgid "" #~ "Subfolder name could not be properly generated. Check to ensure there is " #~ "sufficient image metadata." @@ -2382,6 +2271,10 @@ msgstr "_Weergave" #~ msgstr "Dit apparaat bevat geen afbeeldingen die gedownload kunnen worden." #, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Download van %s afgelopen" + +#, python-format #~ msgid "Deleted %i images from image device" #~ msgstr "%i afbeeldingen van afbeeldingsapparaat verwijderd" @@ -2393,6 +2286,27 @@ msgstr "_Weergave" #~ "Moet dit apparaat of deze partitie gebruikt worden om afbeeldingen van te " #~ "downloaden?" +#~ msgid "Warning:" +#~ msgstr "Waarschuwing:" + +#~ 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 "" +#~ "Deze versie van het programma gebruikt andere voorkeuren dan de vorige. " +#~ "Bepaalde van je vorige voorkeuren zijn ongeldig en kunnen niet aangepast " +#~ "worden. Ze worden naar standaard waarden teruggebracht." + +#~ msgid "Using manually specified path" +#~ msgstr "Manueel ingegeven pad aan het gebruiken" + +#~ msgid "Using backup device" +#~ msgstr "Backup apparaat aan het gebruiken" + +#~ msgid "Using backup devices" +#~ msgstr "Backup apparaten aan het gebruiken" + #~ msgid "Preferences were changed." #~ msgstr "Voorkeuren werden aangepast." @@ -2400,6 +2314,14 @@ msgstr "_Weergave" #~ msgstr "" #~ "toon een lijst van bestandextenties welke het programma herkent en keer terug" +#, python-format +#~ msgid "" +#~ "Preference key '%(key)s' is invalid.\n" +#~ "Expected one of %(value)s" +#~ msgstr "" +#~ "Voorkeurtoets '%(key)s' is ongeldig.\n" +#~ "Eén van %(value)s werd verwacht" + #~ msgid "Subsecond metadata not present in image" #~ msgstr "Subsecond metadata niet aanwezig in de afbeelding" @@ -2407,6 +2329,9 @@ msgstr "_Weergave" #~ msgid "%s metadata is not present in image" #~ msgstr "%s metadata is niet aanwezig in de afbeelding" +#~ msgid "These preferences are not well formed:" +#~ msgstr "Deze voorkeuren zijn niet goed opgesteld:" + #~ msgid "image number was specified but image filename has no number" #~ msgstr "" #~ "afbeeldingsnummer was gespecifieerd, maar de bestandsnaam heeft er geen" @@ -2432,6 +2357,36 @@ msgstr "_Weergave" #~ msgid "Download Folder" #~ msgstr "Download Map" +#~ 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 vrije software; je mag het herverdelen en/of " +#~ "aanpassen onder de termen van de GNU General Public License zoals " +#~ "gepubliceerd door de Free Software Foundation; ofwel versie 2 van de " +#~ "License, of (volgens jou voorkeur) elke latere versie.\n" +#~ "\n" +#~ "Rapid Photo Downloader wordt verdeeld in de hoop dat het nuttig zal zijn, " +#~ "maar ZONDER ENIGE GARANTIE; zelfs zonder de impliciete garantie van " +#~ "VERKOOPBAARHEID of GESCHIKTHEID VOOR EEN BEPAALD DOEL . Zie de GNU General " +#~ "Public License voor meer details.\n" +#~ "\n" +#~ "Je zou een kopie van de GNU General Public License ontvangen moeten hebben " +#~ "samen met Rapid Photo Downloader; indien niet, contacteer de Free Software " +#~ "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, " +#~ "USA." + #~ msgid "Specify what to do when there are no backup devices." #~ msgstr "" #~ "Specifieer wat er dient te gebeuren indien er geen backup apparaten zijn." @@ -2456,6 +2411,30 @@ msgstr "_Weergave" #~ "Specifieer of tekens dienen verwijderd te worden van een afbeeldings- of " #~ "mapnaam die niet door andere besturingssystemen toegestaan zijn." +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Waarde opgeslagen nummer niet aangepast, daar er momenteel een download " +#~ "bezig is" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "'Downloads Vandaag' waarde niet aangepast, daar er momenteel een download " +#~ "bezig is" + +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Copyright Damon Lynch 2007-10" + +#~ msgid "Starting downloads" +#~ msgstr "Downloaden aanvangen" + +#~ msgid "" +#~ "This version of the program is newer than the previously run version. " +#~ "Checking preferences." +#~ msgstr "" +#~ "Deze versie van het programma is recenter dan de vorige. De voorkeuren " +#~ "worden overlopen." + #~ msgid "images skipped" #~ msgstr "afbeeldingen overgeslaan" @@ -2484,6 +2463,10 @@ msgstr "_Weergave" #~ msgstr "Afbeeldingsapparaat: %s\n" #, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Bron: %s\n" + +#, python-format #~ msgid "" #~ "Source: %(source)s\n" #~ "Partially generated filename: %(newname)s\n" @@ -2495,6 +2478,24 @@ msgstr "_Weergave" #~ "Doel: %(destination)s\n" #~ "Probleem: %(problem)s" +#~ msgid "Error:" +#~ msgstr "Fout:" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Doel: %s" + +#~ msgid "Could not create temporary download directory" +#~ msgstr "Kon de tijdelijke downloadfolder niet aanmaken" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Fout: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Doelmap kon niet aangemaakt worden: %(directory)s\n" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2516,6 +2517,14 @@ msgstr "_Weergave" #~ "Los het probleem op, of verander je voorkeuren." #~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Opgelet: de desktop environment notification server is verkeerd ingesteld." + +#~ msgid "Problem with Download Folder" +#~ msgstr "Probleem met de Download Map" + +#~ msgid "" #~ "Sorry, the Download Folder exists but cannot be written to. Please check the " #~ "folder's permissions, or modify your preferences" #~ msgstr "" @@ -2537,6 +2546,20 @@ msgstr "_Weergave" #~ msgstr "0 van %(number)s %(filetypes)s" #, python-format +#~ msgid "" +#~ "The %(filetype)s subfolder preferences had some unnecessary values removed." +#~ msgstr "" +#~ "Er werden overbodige waardes verwijderd van de voorkeuren voor de " +#~ "%(filetype)s subfolder" + +#~ msgid "The following download path could not be created:\n" +#~ msgstr "Het volgende downloadpad kon niet aangemaakt worden:\n" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format #~ msgid "Could not open %s(filetype)s" #~ msgstr "Kon %s(filetype)s niet openen" @@ -2544,6 +2567,15 @@ msgstr "_Weergave" #~ msgid "The %s(filetype)s was not copied." #~ msgstr "De %s(filetype)s werd niet gekopiëerd" +#, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "Apparaten scan afgelopen: geen %(filetypes)s gevonden op %(device)s" + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Apparaten scan afgelopen: %(number)s %(filetypes)s op %(device)s gevonden" + #~ msgid "" #~ "Photos detected with the same filenames, but taken at different times:" #~ msgstr "" @@ -2578,6 +2610,14 @@ msgstr "_Weergave" #~ msgstr "Kon %(filetype)s niet openen" #, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "Backup van %(file_type)s overschreven" + +#, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "%(file_type)s niet gebackuped op %(volume)s" + +#, python-format #~ msgid "" #~ "Metadata is essential for generating subfolder and/or file names.\n" #~ "Source: %s" @@ -2606,9 +2646,39 @@ msgstr "_Weergave" #~ msgid "%(noFiles)s %(filetypes)s skipped" #~ msgstr "%(noFiles)s %(filetypes)s overgeslagen" +#, python-format +#~ msgid "This device has no %(types_searched_for)s to download from." +#~ msgstr "Dit apparaat heeft geen %(types_searched_for)s om te downloaden" + #~ msgid "Photo thumbnail could not be extracted" #~ msgstr "Foto icoontje kon niet opgehaald worden" +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Apparaat: %s\n" + +#~ msgid "A backup location was not found" +#~ msgstr "Een backup locatie werd niet gevonden" + +#~ msgid "No suitable backup volume was found" +#~ msgstr "Geen geldig backup volume gevonden" + +#, python-format +#~ msgid "%(file_type)s could not be backed up" +#~ msgstr "%(file_type)s kon niet gebackuped worden" + +#, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "De %(file_type)s werd niet gebackuped" + +#, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "%(file_type)s niet gebackuped" + +#, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Backup van %(file_type)s bestaat reeds" + #~ msgid "Video skipped" #~ msgstr "Video overgeslagen" @@ -2618,24 +2688,107 @@ msgstr "_Weergave" #~ msgid "Photo skipped" #~ msgstr "Foto overgeslagen" +#~ msgid "No backups can occur" +#~ msgstr "Backups kunnen niet plaatsgrijpen" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Het pad %s kon niet aangemaakt worden" + +#~ msgid "Backup path does not exist" +#~ msgstr "Backup pad bestaat niet" + #~ msgid "No backup device was automatically detected" #~ msgstr "Er werd geen backup apparaat automatisch ontdekt" +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Kon foto of video niet verwijderen van apparaat" + #~ msgid "Video already exists" #~ msgstr "Video bestaat reeds" +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Foto: %(source)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Foto: %(source)s\n" +#~ "Fout: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "The %(file_type)s Download Folder does not exist.\n" +#~ msgstr "De %(file_type)s Download Map bestaat niet\n" + +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "Verwijderde %(number)i %(filetypes)s van apparaat" + +#, python-format +#~ msgid "" +#~ "Sorry, this device location does not exist:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Please resolve the problem, or modify your preferences." +#~ msgstr "" +#~ "Sorry, deze apparaat locatie bestaat niet:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Los het probleem op, of pas de voorkeuren aan." + +#~ msgid "Problem with Device Location Folder" +#~ msgstr "Probleem met de Apparaat Locatie Map" + #~ msgid "photos skipped" #~ msgstr "foto's overgeslagen" #~ msgid "photos downloaded" #~ msgstr "foto's gedownload" +#~ msgid "Problem with Download Folders" +#~ msgstr "Prbleem met de Download Mappen" + +#~ msgid "" +#~ "Sorry, problems were encountered with your download folders. Please fix the " +#~ "problems or modify the preferences.\n" +#~ "\n" +#~ msgstr "" +#~ "Sorry, er waren problemen met je download mappen. Los deze problemen op of " +#~ "pas de voorkeuren aan.\n" +#~ "\n" + +#, python-format +#~ msgid "Failed to create default video download folder %(folder)s" +#~ msgstr "Kon de standaard video download map %(folder)s niet aanmaken" + +#, python-format +#~ msgid "Creating photo download folder %(folder)s" +#~ msgstr "Foto download map %(folder)s wordt aangemaakt" + +#, python-format +#~ msgid "Creating video download folder %(folder)s" +#~ msgstr "Video download map %(folder)s wordt aangemaakt" + +#, python-format +#~ msgid "Failed to create default photo download folder %(folder)s" +#~ msgstr "Kon de standaard foto download map %(folder)s niet aanmaken" + +#, python-format +#~ msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#~ msgstr "De %(file_type)s Download Map bestaat maar is niet beschrijfbaar.\n" + #~ msgid "videos skipped" #~ msgstr "video's overgeslagen" #~ msgid "videos downloaded" #~ msgstr "video's gedownload" +#~ msgid "\n" +#~ msgstr "\n" + #~ msgid "image or video number was specified but filename has no number" #~ msgstr "" #~ "beeld- of videonummer werd opgegeven maar de bestandsnaam heeft geen nummer" @@ -2658,6 +2811,11 @@ msgstr "_Weergave" #~ msgid "%s metadata is not present" #~ msgstr "%s metadata ontbreekt" +#~ msgid "Exit program if download completes without any warnings or errors" +#~ msgstr "" +#~ "Verlaat het programma als de download zonder verwittigingen noch fouten " +#~ "beëindigd wordt." + #~ msgid "" #~ "Choose whether to skip downloading the file, or to add a unique indentifier." #~ msgstr "" @@ -2682,5 +2840,171 @@ msgstr "_Weergave" #~ msgid "The %(filetype)s was not copied." #~ msgstr "De %(filetype)s werd niet gekopiëerd" +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Bron: %(source)s\n" +#~ "Doel: %(destination)s\n" +#~ "%(problem)s" + +#~ msgid "" +#~ "Downloading from a card reader always works and is generally much faster. It " +#~ "is strongly recommended to use a card reader." +#~ msgstr "" +#~ "Het downloaden van een kaartlezer werkt altijd en is meestal sneller. Het " +#~ "wordt tenstelligste aanbevolen een kaartlezer te gebruiken." + +#~ msgid "Downloading From Cameras" +#~ msgstr "Downloaden van Camera's" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "" +#~ "Het rechtstreeks downloaden vanaf een camera kan slecht, tot helemaal niet " +#~ "werken" + +#~ msgid "_Show this message again" +#~ msgstr "_Toon dit bericht opnieuw" + +#, python-format +#~ msgid "Attempting to download %s files" +#~ msgstr "Proberen om %s bestanden te downloaden" + +#~ msgid "Please check your system and try again." +#~ msgstr "Controlleer je systeem en probeer opnieuw" + +#~ msgid "Path" +#~ msgstr "Pad" + +#~ msgid "Date" +#~ msgstr "Datum" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s werd niet gedownload" + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s was met succes gedownload" + +#~ msgid "File" +#~ msgstr "Bestand" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "Type" +#~ msgstr "Type" + +#, python-format +#~ msgid "%(filetype)s was downloaded but there were problems backing up" +#~ msgstr "" +#~ "%(filetype)s werd gedownload maar er waren problemen tijdens het backuppen" + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s werd gedownload met opmerkingen" + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s is klaar om gedownload te worden" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s zal gedownload worden met opmerkingen" + +#, python-format +#~ msgid "%(filetype)s is about to be downloaded" +#~ msgstr "%(filetype)s staat op het punt gedownload te worden" + +#, python-format +#~ msgid "%(filetype)s was neither downloaded nor backed up" +#~ msgstr "%(filetype)s werd niet gedownload noch gebackupped" + +#~ msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#~ msgstr "" +#~ "Geef een nieuwe Job Code op en druk op Enter, of selecteer een bestaande Job " +#~ "Code" + +#~ msgid "Displaying warning about downloading directly from camera" +#~ msgstr "" +#~ "Opmerking vertonen betreffende het rechtstreeks downloaden vanaf een camera" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s kan niet gedownload worden" + #~ msgid "Preview" #~ msgstr "Voorbeeld" + +#~ msgid "_Download All" +#~ msgstr "_Alles Downloaden" + +#, python-format +#~ msgid "Warning: backup device %(device)s is currently being downloaded from" +#~ msgstr "" +#~ "Opmerking: er wordt momenteel gedownload vanaf backup apparaat %(device)s" + +#~ msgid "D_ownload Selected" +#~ msgstr "D_ownload geselecteerd" + +#~ msgid "_Resume" +#~ msgstr "_Hervatten" + +#~ msgid "Subfolder and filename preferences were changed." +#~ msgstr "Subfolder en bestandsnaam voorkeuren zijn veranderd." + +#~ msgid "Download device settings preferences were changed." +#~ msgstr "De download apparaat instellingen zijn veranderd" + +#~ msgid "Backup preferences were changed." +#~ msgstr "Backup voorkeuren zijn veranderd." + +#~ msgid "Select _All" +#~ msgstr "Selecteer _Alles" + +#~ msgid "Select All Vi_deos" +#~ msgstr "Selecteer Alle Vi_deo's" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Selecteer Alle Fo_to's" + +#~ msgid "Preview _Folders" +#~ msgstr "Preview _Mappen" + +#~ msgid "P_review Columns" +#~ msgstr "P_review Kolommen" + +#~ msgid "Download folder preferences were changed." +#~ msgstr "Downloadmap voorkeuren zijn veranderd." + +#~ msgid "Se_lect None" +#~ msgstr "Se_lecteer Geen Enkele" + +#~ msgid "_Device" +#~ msgstr "_Apparaat" + +#~ msgid "_Path" +#~ msgstr "_Pad" + +#~ msgid "_Preview" +#~ msgstr "_Voorbeeld" + +#~ msgid "_Filename" +#~ msgstr "_Bestandsnaam" + +#~ msgid "_Size" +#~ msgstr "_Grootte" + +#~ msgid "_Type" +#~ msgstr "_Type" + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Fout: %(inst)s" + +#, python-format +#~ msgid "%(free)s available" +#~ msgstr "%(free)s beschikbaar" diff --git a/po/pt_BR.po b/po/pt_BR.po index c52ae07..519a6cb 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -7,255 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" -"PO-Revision-Date: 2011-02-13 13:21+0000\n" -"Last-Translator: Sam Samuels <gemini_sam_samuels@hotmail.co.uk>\n" +"POT-Creation-Date: 2011-04-10 19:59-0500\n" +"PO-Revision-Date: 2011-04-11 01:47+0000\n" +"Last-Translator: Marco <marcodefreitas@gmail.com>\n" "Language-Team: Brazilian Portuguese <pt_BR@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: 2011-03-20 22:12+0000\n" -"X-Generator: Launchpad (build 12617)\n" +"X-Launchpad-Export-Date: 2011-04-21 06:12+0000\n" +"X-Generator: Launchpad (build 12883)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:104 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "Nova Iorque" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "Manila" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "Praga" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "Helsinque" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "Teerã" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "Paris" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "Berlim" - -#: rapid/rapid.py:463 -msgid "Sydney" -msgstr "Sydney" - -#: rapid/rapid.py:464 -msgid "Budapest" -msgstr "Budapeste" - -#: rapid/rapid.py:464 -msgid "Rome" -msgstr "Roma" - -#: rapid/rapid.py:464 -msgid "Moscow" -msgstr "Moscou" - -#: rapid/rapid.py:464 -msgid "Delhi" -msgstr "Deli" - -#: rapid/rapid.py:464 -msgid "Warsaw" -msgstr "Varsóvia" - -#: rapid/rapid.py:465 -msgid "Jakarta" -msgstr "Jacarta" - -#: rapid/rapid.py:465 -msgid "Madrid" -msgstr "Madri" - -#: rapid/rapid.py:465 -msgid "Stockholm" -msgstr "Estocolmo" - -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" -msgstr "Valor de \"Descargas Hoje\" é inválido.\n" - -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" -msgstr "Redefinindo valor para zero.\n" - -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "Valor de \"começo do dia\" é inválido.\n" - -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" -msgstr "A restabelecer tempo em meia-noite.\n" - -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" -msgstr "Erro causado pelas preferêcias em \"renomear fotografias\"" - -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Erro encontrado nas seguintes preferências:\n" - -#: rapid/rapid.py:609 -msgid "Resetting to default values." -msgstr "A restabelecer valores em seus padrões." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" -msgstr "Etiqueta" - -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" -msgstr "Erro causado pelas preferêcias em \"renomear vídeos\"" - -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" -msgstr "" -"Erro causado pelas preferêcias de subdiretórios em \"diretórios de " -"fotografias\"" - -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" -msgstr "" -"Erro causado pelas preferêcias de subdiretórios em \"diretórios de vídeo\"" - -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" -msgstr "fotos e vídeos" - -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 -msgid "photos" -msgstr "fotos" - -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "Selecione o diretório para baixar as fotos para" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" -msgstr "Selecione o diretório para baixar os vídeos para" - -#: rapid/rapid.py:1055 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Escolha um diretório que contenha %(file_types)s" - -#: rapid/rapid.py:1077 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "" -"Escolha um diretório para o armazenamento de cópias de segurança de " -"%(file_types)s" - -#. 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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" -"<i><b>Aviso:</b> As meta-Informações disponíveis são insuficiente à geração " -"de um nome para arquivos. Por favor, faça uso de outras opções de " -"nomeação.</i>" - -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" -msgstr "" -"<i><b>Aviso:</b> As meta-Informações disponíveis são insuficiente à geração " -"de um nome para subdiretórios. Por favor, faça uso de outras opções de " -"nomeação.</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:1198 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Exemplo: %s</i>" - -#: rapid/rapid.py:1224 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"Apesar da execução de descargas, o valor de \"descargas hoje\" não foi " -"atualizado." - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Apesar da execução de descargas, o valor de \"número acumulado\" não foi " -"atualizado." - -#: rapid/rapid.py:1270 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" -"Alguns valores foram julgados desnecessários e foram, conseqüentemente, " -"removidos das prefências de subdiretórios de %(filetype)s." - -#. Preferences list is now empty -#: rapid/rapid.py:1275 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" -"As preferências definidas para os subdiretórios de %(filetype)s são " -"inválidas e não poderão ser usadas.\n" -"Elas serão restabelecidas em seus valores padrão." - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" -msgstr "foto" - -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" -msgstr "vídeo" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -msgid "externaldrive1" -msgstr "disco_externo_1" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1529 -msgid "externaldrive2" -msgstr "disco_externo_2" - -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" -msgstr "fotos ou vídeos" - -#: rapid/rapid.py:1556 -msgid "videos" -msgstr "vídeos" - -#: rapid/rapid.py:1568 +#: rapid/rapid.py:109 #, python-format msgid "" "%(date)s\n" @@ -264,361 +31,320 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1570 +#: rapid/rapid.py:111 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1573 -#, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" - -#: rapid/rapid.py:1580 +#: rapid/rapid.py:114 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" -msgstr "subdiretório e nome de arquivo" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:148 +msgid "Device" +msgstr "Dispositivo" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" -msgstr "nome de arquivo" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:165 +msgid "Size" +msgstr "Tamanho" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" -msgstr "subdiretório" +#: rapid/rapid.py:168 +msgid "Download Progress" +msgstr "Progresso da transferência" + +#: rapid/rapid.py:312 +#, python-format +msgid "%(device)s did not unmount" +msgstr "" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 +#: rapid/rapid.py:1091 msgid "scanning..." msgstr "verificando..." -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" -msgstr "O seguinte destino de descarga não pôde ser criado:\n" +#: rapid/rapid.py:1807 +msgid "Download" +msgstr "" -#: rapid/rapid.py:1819 +#: rapid/rapid.py:1810 +msgid "Pause" +msgstr "" + +#: rapid/rapid.py:1912 #, python-format -msgid "%(path)s: " -msgstr "%(path)s: " +msgid "" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" +msgstr "" -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 +#: rapid/rapid.py:1915 +#, python-format +msgid "" +"This download folder is invalid:\n" +"%s" +msgstr "" + +#: rapid/rapid.py:1916 msgid "Download cannot proceed" msgstr "A descarga não pôde ser levada a cabo" -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." -msgstr "Há um erro nas preferências do programa." - -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Por favor, tente novamente após revisar as preferências e reiniciar o " -"programa." +#: rapid/rapid.py:2130 +msgid "About 1 second remaining" +msgstr "Faltando 1 segundo aproximadamente" -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 +#: rapid/rapid.py:2132 #, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)s" +msgid "About %i seconds remaining" +msgstr "Faltando %i segundos aproximadamente" -#. 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 photos 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:2019 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Varredura do dispositivo completa: %(number)s %(filetypes)s encontrados em " -"%(device)s" +#: rapid/rapid.py:2134 +msgid "About 1 minute remaining" +msgstr "Faltando 1 minuto aproximadamente" -#: rapid/rapid.py:2026 +#. 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:2139 #, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "" -"Varredura do dispositivo completa: não foram encontrados %(filetypes)s em " -"%(device)s" +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Faltando %(minutes)i:%(seconds)02i minutos aproximadamente" -#. 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:2047 -msgid "The device can now be safely removed" -msgstr "O dispositivo poderá agora ser removido com segurança" +#: rapid/rapid.py:2151 rapid/preferencesdialog.py:822 rapid/rpdfile.py:110 +msgid "photos and videos" +msgstr "fotos e vídeos" + +#: rapid/rapid.py:2153 rapid/rpdfile.py:112 +msgid "photos or videos" +msgstr "fotos ou vídeos" + +#: rapid/rapid.py:2156 rapid/rapid.py:2661 rapid/rpdfile.py:115 +msgid "videos" +msgstr "vídeos" + +#: rapid/rapid.py:2158 rapid/preferencesdialog.py:1371 rapid/rpdfile.py:117 +#: rapid/rpdfile.py:266 +msgid "video" +msgstr "vídeo" + +#: rapid/rapid.py:2161 rapid/rapid.py:2659 rapid/preferencesdialog.py:824 +#: rapid/rpdfile.py:120 +msgid "photos" +msgstr "fotos" + +#. check subfolder preferences for bad values +#: rapid/rapid.py:2163 rapid/preferencesdialog.py:1370 rapid/rpdfile.py:122 +#: rapid/rpdfile.py:246 +msgid "photo" +msgstr "foto" -#: rapid/rapid.py:2053 +#: rapid/rapid.py:2188 #, python-format msgid "%(noFiles)s %(filetypes)s downloaded" msgstr "%(noFiles)s %(filetypes)s descarregados" -#: rapid/rapid.py:2056 +#: rapid/rapid.py:2192 #, python-format msgid "%(noFiles)s %(filetypes)s failed to download" msgstr "%(noFiles)s %(filetypes)s não puderam ser descarregados" -#: rapid/rapid.py:2059 rapid/rapid.py:5901 +#: rapid/rapid.py:2195 rapid/rapid.py:2247 msgid "warnings" msgstr "avisos" -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" -msgstr "erros" +#: rapid/rapid.py:2204 +msgid "All downloads complete" +msgstr "Todos os downloads completos" -#: rapid/rapid.py:2091 +#: rapid/rapid.py:2210 rapid/rapid.py:2219 rapid/rapid.py:2228 +#: rapid/rapid.py:2237 rapid/rapid.py:2245 #, python-format -msgid "Source: %s\n" -msgstr "Origem: %s\n" +msgid "%(number)s %(numberdownloaded)s" +msgstr "%(number)s %(numberdownloaded)s" -#: rapid/rapid.py:2093 +#: rapid/rapid.py:2212 rapid/rapid.py:2230 #, python-format -msgid "Device: %s\n" -msgstr "Dispositivo: %s\n" +msgid "%(filetype)s downloaded" +msgstr "%(filetype)s downloaded" -#: rapid/rapid.py:2094 +#: rapid/rapid.py:2221 rapid/rapid.py:2239 #, python-format -msgid "Destination: %s" -msgstr "Destino: %s" - -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" -msgstr "O diretório temporário de descarga não pôde ser criado" - -#: rapid/rapid.py:2098 -msgid "Error:" -msgstr "Erro:" +msgid "%(filetype)s failed to download" +msgstr "" -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" -msgstr "Diretório para armazenamento de cópias de segurança é inexistente" +#. e.g.: 3 of 205 photos and videos (202 remaining) +#: rapid/rapid.py:2276 +#, python-format +msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" +msgstr "%(number)s de %(total)s %(filetypes)s (%(remaining)s restantes)" -#: rapid/rapid.py:2123 +#. e.g.: 205 of 205 photos and videos +#: rapid/rapid.py:2283 #, python-format -msgid "The path %s could not be created" -msgstr "Diretório %s não pôde ser criado" +msgid "%(number)s of %(total)s %(filetypes)s" +msgstr "%(number)s de %(total)s %(filetypes)s" -#: rapid/rapid.py:2124 -msgid "No backups can occur" -msgstr "Não foi possível a criação de cópias de segurança" +#: rapid/rapid.py:2665 +msgid "Free space:" +msgstr "Espaço livre:" -#: rapid/rapid.py:2153 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2677 #, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +msgid "(%(file_type)s)" msgstr "" -"Origem: %(source)s\n" -"Destino: %(destination)s\n" -"%(problem)s" -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2681 #, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" +msgid "%(free)s %(file_type)s" msgstr "" -"Origem: %(source)s\n" -"Destino: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "Por favor, tente novamente após uma revisão do sistema." -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" -"Foram detectadas fotografias de mesmo nome, mas de horários diferentes" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2686 +msgid "; " +msgstr "; " -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" -msgstr "A foto já foi baixada" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2691 +msgid "." +msgstr "." -#: rapid/rapid.py:2260 rapid/rapid.py:2659 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2697 #, python-format -msgid "Source: %(source)s" -msgstr "Origem: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" +msgid "%(free)s free" msgstr "" -"Um novo dia teve início - o número seqüencial \"descargas hoje\" foi " -"restabelecido." - -#: rapid/rapid.py:2529 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Já existem cópias de segurança de %(file_type)s" -#: rapid/rapid.py:2533 -#, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "As cópias de segurança de %(file_type)s foram sobrescritas" - -#: rapid/rapid.py:2537 +#. user manually specified backup location +#: rapid/rapid.py:2703 #, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "Não foram feitas cópias de segurança de %(file_type)s em %(volume)s" +msgid "Backing up to %(path)s" +msgstr "A criar cópias de segurança em %(path)s" -#: rapid/rapid.py:2539 +#: rapid/rapid.py:2708 #, python-format -msgid "%(file_type)s not backed up" -msgstr "Não foram feitas cópias de segurança de %(file_type)s" +msgid "%(freespace)s. %(backuppaths)s." +msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" -msgstr "Erro ao criar cópias de segurança" +#: rapid/rapid.py:2737 +msgid "Program preferences are invalid" +msgstr "" -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Diretório de destino não pôde ser criado: %(directory)s\n" +#: rapid/rapid.py:2842 rapid/rpdfile.py:247 +msgid "Photo" +msgstr "Fotografia" -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" -msgstr "Erro: %(inst)s" +#: rapid/rapid.py:2844 rapid/rpdfile.py:267 +msgid "Video" +msgstr "Vídeo" -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 +#: rapid/rapid.py:2853 #, python-format -msgid "The %(file_type)s was not backed up." -msgstr "Não foram feitas cópias de segurança de %(file_type)s." +msgid "%(file_type)s download folder does not exist" +msgstr "" -#: rapid/rapid.py:2595 rapid/rapid.py:2645 +#: rapid/rapid.py:2855 rapid/rapid.py:2869 rapid/rapid.py:2882 #, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Erro: %(errno)s %(strerror)s" +msgid "Folder: %s" +msgstr "" -#: rapid/rapid.py:2658 +#: rapid/rapid.py:2867 #, python-format -msgid "%(file_type)s could not be backed up" -msgstr "Não puderam ser feitas cópias de segurança de %(file_type)s." - -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" -msgstr "Não foi encontrado um volume adequado às cópias de seguraça." - -#: rapid/rapid.py:2663 -msgid "A backup location was not found" +msgid "%(file_type)s download folder is invalid" msgstr "" -"Um dos locais destinado ao armazenamento de cópias de segurança não pôde ser " -"encontrado" -#: rapid/rapid.py:2717 +#: rapid/rapid.py:2880 #, python-format -msgid "This device has no %(types_searched_for)s to download from." +msgid "%(file_type)s download folder is not writable" msgstr "" -"Não há %(types_searched_for)s presentes nesse dispositivo, o que torna uma " -"descarga desnecessária." -#: rapid/rapid.py:2813 -#, python-format -msgid "Download has started from %s" -msgstr "Transferência foi iniciada em %s" +#: rapid/rapid.py:2958 +msgid "Thumbnails" +msgstr "Miniaturas" -#: rapid/rapid.py:2817 +#. 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:3005 #, python-format -msgid "Attempting to download %s files" -msgstr "Tentando baixar %s arquivos" +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" +msgstr "" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s" -msgstr "%(number)s de %(total)s %(filetypes)s" +#: rapid/rapid.py:3006 +msgid "display debugging information when run from the command line" +msgstr "" -#: rapid/rapid.py:2913 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" -msgstr "%(number)s de %(total)s %(filetypes)s (%(remaining)s restantes)" +#: rapid/rapid.py:3007 +msgid "only output errors to the command line" +msgstr "" -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" -msgstr "Não foi possível apagar as fotos ou vídeos do dispositivo" +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3009 +msgid "list photo and video file extensions the program recognizes and exit" +msgstr "" -#: rapid/rapid.py:2939 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" +#: rapid/rapid.py:3010 +msgid "reset all program settings and preferences and exit" msgstr "" -"Foto: %(source)s\n" -"Erro: %(errno)s %(strerror)s" +"Restabelecer todas as configurações e preferências do programa e fechá-lo" -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" -msgstr "Foto: %(source)s" +#: rapid/rapid.py:3023 +msgid "Photos:" +msgstr "Fotos:" -#: rapid/rapid.py:2945 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "Foram apagados(as) %(number)i %(filetypes)s do dispositivo" +#: rapid/rapid.py:3023 +msgid "Videos:" +msgstr "Vídeos:" -#: rapid/rapid.py:2958 +#: rapid/rapid.py:3028 #, python-format -msgid "Download complete from %s" -msgstr "Transferência concluída de %s" - -#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. -#: rapid/rapid.py:3073 rapid/rapid.py:3542 -msgid "Device" -msgstr "Dispositivo" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" -msgstr "Tamanho" - -#: rapid/rapid.py:3081 -msgid "Download Progress" -msgstr "Progresso da transferência" +msgid "and %s" +msgstr "e %s" -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" -msgstr "Baixando das câmeras" +#: rapid/rapid.py:3036 +msgid "All settings and preferences have been reset" +msgstr "Todas as configurações e preferências foram redefinidas" -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" +#: rapid/rapid.py:3045 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." msgstr "" -"Descarregar arquivos diretamente de uma câmera pode ser muito problemático" -#: rapid/rapid.py:3176 +#: rapid/copyfiles.py:142 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:332 rapid/subfolderfile.py:350 +#, python-format msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." +"%(problem)s\n" +"File: %(file)s" msgstr "" -"O uso de leitores de cartão é recomendado. Eles funcionam sempre e são " -"geralmente mais rápidos." - -#: rapid/rapid.py:3190 -msgid "_Show this message again" -msgstr "_Exibir esta mensagem novamente" -#: rapid/rapid.py:3225 +#: rapid/device.py:79 msgid "Device Detected" msgstr "Dispositivo detectado" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 +#: rapid/device.py:88 msgid "" "Should this device or partition be used to download photos or videos from?" msgstr "" @@ -626,1076 +352,1160 @@ msgstr "" "dispositivo ou partição?" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 +#: rapid/device.py:107 msgid "_Remember this choice" msgstr "_Relembrar esta escolha" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s selecionado para transferência de" +#: rapid/downloadtracker.py:217 +msgid "MB/s" +msgstr "MB/s" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" -msgstr "Este dispositivo ou partição será recordado para futuras descargas" +#: rapid/generatenameconfig.py:143 +msgid "Date time" +msgstr "Data e hora" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s foi rejeitado como um dispositivo de transferência" +#: rapid/generatenameconfig.py:144 +msgid "Text" +msgstr "Texto" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" -msgstr "Este dispositivo ou partição será rejeitado para futuras descargas" +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Nome do arquivo" -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" -msgstr "Remover todas as etiquetas?" +#: rapid/generatenameconfig.py:146 +msgid "Metadata" +msgstr "Metadados" -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" -msgstr "Deseja realmente remover todas as etiquetas?" +#: rapid/generatenameconfig.py:147 +msgid "Sequences" +msgstr "Seqüências" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" -msgstr "Definir uma etiqueta" +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:549 +msgid "Job code" +msgstr "Etiqueta" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" -msgstr "Defina uma nova etiqueta or selecione uma já presente" +#: rapid/generatenameconfig.py:150 +msgid "Image date" +msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" -msgstr "Defina uma nova etiqueta" +#: rapid/generatenameconfig.py:151 +msgid "Video date" +msgstr "" -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" -msgstr "Etiqueta:" +#: rapid/generatenameconfig.py:152 +msgid "Today" +msgstr "Hoje" -#: rapid/rapid.py:3425 -msgid "Job Code entered" -msgstr "Etiqueta definida" +#: rapid/generatenameconfig.py:153 +msgid "Yesterday" +msgstr "Ontem" -#: rapid/rapid.py:3427 -msgid "Job Code not entered" -msgstr "Etiqueta não definida" +#. Translators: Download time is the time and date that the download started (when the user clicked the Download button) +#: rapid/generatenameconfig.py:155 +msgid "Download time" +msgstr "Início do download" -#: rapid/rapid.py:3477 -msgid "Status" -msgstr "Status" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:157 +msgid "Name + extension" +msgstr "" -#: rapid/rapid.py:3485 -msgid "Type" -msgstr "Tipo" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:159 +msgid "Name" +msgstr "Nome" -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" -msgstr "Fotografia" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:161 +msgid "Extension" +msgstr "" -#: rapid/rapid.py:3496 -msgid "File" -msgstr "Arquivo" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:163 +msgid "Image number" +msgstr "" -#: rapid/rapid.py:3511 -msgid "Job Code" -msgstr "Etiqueta" +#: rapid/generatenameconfig.py:164 +msgid "Video number" +msgstr "" -#: rapid/rapid.py:3521 -msgid "Date" -msgstr "Data" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:166 +msgid "Aperture" +msgstr "Abertura" -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" -msgstr "Nome do arquivo" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:168 +msgid "ISO" +msgstr "ISO" -#: rapid/rapid.py:3564 -msgid "Path" -msgstr "Caminho" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:170 +msgid "Exposure time" +msgstr "Tempo de exposição" -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s foi descarregado(a) com êxito." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:172 +msgid "Focal length" +msgstr "Distância focal" -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s não foi descarregado(a)." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:174 +msgid "Camera make" +msgstr "" -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s foi descarregado(a) com ressalvas." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:176 +msgid "Camera model" +msgstr "Modelo da câmera" -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:178 +msgid "Short camera model" msgstr "" -"%(filetype)s foi descarregado(a), mas houve problemas durante a criação de " -"cópias de segurança." -#: rapid/rapid.py:3982 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:180 +msgid "Hyphenated short camera model" msgstr "" -"%(filetype)s não foi descarregado(a), nem cópias de segurança foram criadas." -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s está proto para a descarga" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:182 +msgid "Serial number" +msgstr "Número de série" -#: rapid/rapid.py:3986 -#, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "%(filetype)s será descarregado" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:184 +msgid "Shutter count" +msgstr "" -#: rapid/rapid.py:3988 -#, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s será descarregado(a) com ressalvas" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:186 +msgid "Owner name" +msgstr "" -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s não pode ser descarregado(a)." +#: rapid/generatenameconfig.py:187 +msgid "Codec" +msgstr "Codec" -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#: rapid/generatenameconfig.py:188 +msgid "Width" +msgstr "Largura" + +#: rapid/generatenameconfig.py:189 +msgid "Height" +msgstr "Altura" + +#: rapid/generatenameconfig.py:190 +msgid "Length" msgstr "" -"Defina uma nova etiqueta e confirme com a tecla Enter, ou selecione uma " -"etiqueta já existente" -#: rapid/rapid.py:5034 -#, python-format -msgid "%(free)s available" -msgstr "%(free)s disponíveis ao uso" +#: rapid/generatenameconfig.py:191 +msgid "Frames Per Second" +msgstr "Quadros Por Segundo" -#. user manually specified backup location -#: rapid/rapid.py:5040 -#, python-format -msgid "Backing up to %(path)s" -msgstr "A criar cópias de segurança em %(path)s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:193 +msgid "Downloads today" +msgstr "" -#: rapid/rapid.py:5045 -#, python-format -msgid "%(freespace)s. %(backuppaths)s." -msgstr "%(freespace)s. %(backuppaths)s." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:195 +msgid "Session number" +msgstr "" -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:197 +msgid "Subfolder number" msgstr "" -"Desculpe, esta localização do dispositivo não existe:\n" -"%(path)s" -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" -msgstr "Problema com o dispositivo local da pasta" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:199 +msgid "Stored number" +msgstr "" -#: rapid/rapid.py:5067 -msgid "Video" -msgstr "Vídeo" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/generatenameconfig.py:201 +msgid "Sequence letter" +msgstr "Seqüência de letras" -#: rapid/rapid.py:5074 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "A %(file_type)s Pasta de Download não existe.\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:203 +msgid "All digits" +msgstr "Todos os dígitos" -#: rapid/rapid.py:5083 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "A %(file_type)s Pasta de Download existe mas não pode ser escrita.\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:205 +msgid "Last digit" +msgstr "Último dígito" -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" -"Desculpe, alguns problemas foram encontrados com as suas pastas de download. " -"Por favor, corrija os problemas ou modifique as preferências.\n" -"\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:207 +msgid "Last 2 digits" +msgstr "Últimos 2 dígitos" -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" -msgstr "Problema com a Pasta de Download" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:209 +msgid "Last 3 digits" +msgstr "Últimos 3 dígitos" -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" -msgstr "Problemas com as Pastas de Download" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:211 +msgid "Last 4 digits" +msgstr "Últimos 4 dígitos" -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." -msgstr "Algumas preferências serão restabelecidas." +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/generatenameconfig.py:213 +msgid "Original Case" +msgstr "Caixa de tetxo original" -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" -msgstr "Resultados de aviso sobre o download diretamente da câmera" +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/generatenameconfig.py:215 +msgid "UPPERCASE" +msgstr "CAIXA ALTA" -#: rapid/rapid.py:5149 -#, python-format -msgid "Prompting whether to use %s" -msgstr "Solicitação de se usar %s" +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/generatenameconfig.py:217 +msgid "lowercase" +msgstr "caixa baixa" -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" -msgstr "Solicitando o código de trabalho" +#: rapid/generatenameconfig.py:218 +msgid "One digit" +msgstr "Um dígito" -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Já foi solicitado o Trabalho Código, não perguntar de novo" +#: rapid/generatenameconfig.py:219 +msgid "Two digits" +msgstr "Dois dígitos" -#: rapid/rapid.py:5197 -msgid "Starting downloads" -msgstr "Iniciando downloads" +#: rapid/generatenameconfig.py:220 +msgid "Three digits" +msgstr "Três dígitos" -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "A partir de downloads que foram à espera de um código de trabalho" +#: rapid/generatenameconfig.py:221 +msgid "Four digits" +msgstr "Quatro dígitos" -#: rapid/rapid.py:5248 -#, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "Criando pasta de download de fotos %(folder)s" +#: rapid/generatenameconfig.py:222 +msgid "Five digits" +msgstr "Cinco dígitos" -#: rapid/rapid.py:5253 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "Falha ao criar pasta padrão de download de fotos %(folder)s" +#: rapid/generatenameconfig.py:223 +msgid "Six digits" +msgstr "Seis dígitos" -#: rapid/rapid.py:5257 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "Criando pasta de download de vídeo %(folder)s" +#: rapid/generatenameconfig.py:224 +msgid "Seven digits" +msgstr "Sete dígitos" -#: rapid/rapid.py:5262 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "Falha ao criar pasta padrão de download de vídeo %(folder)s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:226 +msgid "Subseconds" +msgstr "Subsegundos" -#: rapid/rapid.py:5287 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" -msgstr "" -"Uma nova versão deste programa foi executado anteriormente nesse " -"computador.\n" -"\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:228 +msgid "YYYYMMDD" +msgstr "AAAAMMDD" -#: rapid/rapid.py:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"As preferências do programa parecem ser válidas, mas por favor verifique-los " -"para garantir o funcionamento correto." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:230 +msgid "YYYY-MM-DD" +msgstr "AAAA-MM-DD" -#: rapid/rapid.py:5291 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "Algumas preferências são inválidas e serão portanto restabelecidas." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:232 +msgid "YYMMDD" +msgstr "AAMMDD" -#: rapid/rapid.py:5292 -msgid "Warning:" -msgstr "Atenção:" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:234 +msgid "YY-MM-DD" +msgstr "AA-MM-DD" -#: rapid/rapid.py:5297 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." -msgstr "" -"Esta versão do programa é mais recente que a versão anteriormente executada. " -"Verificar preferências." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:236 +msgid "MMDDYYYY" +msgstr "MMDDAAAA" -#: rapid/rapid.py:5304 -msgid "Preferences were modified." -msgstr "As preferências foram modificadas." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:238 +msgid "MMDDYY" +msgstr "MMDDAA" -#: rapid/rapid.py:5305 -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 versão do programa utiliza diferentes preferências que a versão antiga. " -"Suas preferências foram atualizadas.\n" -"\n" -"Por favor verifique-los para garantir o funcionamento correto." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:240 +msgid "MMDD" +msgstr "MMDD" -#: rapid/rapid.py:5309 -msgid "No preferences needed to be changed." -msgstr "Nenhuma preferência precisou ser mudada." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:242 +msgid "DDMMYYYY" +msgstr "DDMMAAAA" -#: rapid/rapid.py:5311 -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 "" -"Pelo programa ser de uma versão mais avançada, algumas preferências são " -"agora obsoletas e serão portanto restabelecidas em seus valores padrão." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:244 +msgid "DDMMYY" +msgstr "DDMMAA" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:246 +msgid "YYYY" +msgstr "AAAA" -#: rapid/rapid.py:5321 -msgid "Problem using pynotify." -msgstr "Problema com pynotify." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:248 +msgid "YY" +msgstr "AA" -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." -msgstr "Falha ao receber recursos do servidor pynotify." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:250 +msgid "MM" +msgstr "MM" -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Atenção: servidor de notificações ambiente desktop está configurado " -"incorretamente." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:252 +msgid "DD" +msgstr "DD" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:254 +msgid "HHMMSS" +msgstr "HHMMSS" -#: rapid/rapid.py:5396 -msgid "and" -msgstr "e" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:256 +msgid "HHMM" +msgstr "HHMM" -#: rapid/rapid.py:5401 -msgid "Using backup devices" -msgstr "Usando dispositivos de backup" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:258 +msgid "HH-MM-SS" +msgstr "HH-MM-SS" -#: rapid/rapid.py:5403 -msgid "Using backup device" -msgstr "Usando o dispositivo de backup" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:260 +msgid "HH-MM" +msgstr "HH-MM" -#: rapid/rapid.py:5405 -msgid "No backup devices detected" -msgstr "Nenhum dispositivo de backup detectado" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:262 +msgid "HH" +msgstr "HH" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:264 +msgid "MM (minutes)" +msgstr "MM (minutos)" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:266 +msgid "SS" +msgstr "SS" + +#: rapid/preferencesdialog.py:370 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "" -#: rapid/rapid.py:5455 rapid/rapid.py:5617 +#: rapid/preferencesdialog.py:372 #, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Dispositivo %(device)s (%(path)s ignorado" +msgid "Subfolder preferences should not end with a %s" +msgstr "" -#: rapid/rapid.py:5576 +#: rapid/preferencesdialog.py:376 #, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Detectado %(device)s com o caminho %(path)s" +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" -msgstr "Iniciar download automaticamente é verdadeiro" +#: rapid/preferencesdialog.py:389 rapid/preferencesdialog.py:672 +msgid "Remove all Job Codes?" +msgstr "Remover todas as etiquetas?" -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" -msgstr "Iniciar download automaticamente é falso" +#: rapid/preferencesdialog.py:406 rapid/preferencesdialog.py:689 +msgid "Should all Job Codes be removed?" +msgstr "Deseja realmente remover todas as etiquetas?" -#: rapid/rapid.py:5635 -msgid "Using manually specified path" -msgstr "Usando o caminho especificado manualmente" +#: rapid/preferencesdialog.py:436 +msgid "Error in Photo Rename preferences" +msgstr "Erro causado pelas preferêcias em \"renomear fotografias\"" -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" +#: rapid/preferencesdialog.py:617 +msgid "Error in Video Rename preferences" +msgstr "Erro causado pelas preferêcias em \"renomear vídeos\"" + +#: rapid/preferencesdialog.py:638 +msgid "Error in Photo Download Subfolders preferences" msgstr "" -"Atenção: dispositivo de backup %(device)s atualmente está sendo baixado" +"Erro causado pelas preferêcias de subdiretórios em \"diretórios de " +"fotografias\"" -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" -msgstr "D_ownload selecionados" +#: rapid/preferencesdialog.py:655 +msgid "Error in Video Download Subfolders preferences" +msgstr "" +"Erro causado pelas preferêcias de subdiretórios em \"diretórios de vídeo\"" -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" -msgstr "Todos os downloads completos" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:714 +msgid "Enter a Job Code" +msgstr "Definir uma etiqueta" -#: rapid/rapid.py:5837 -msgid "MB/s" -msgstr "MB/s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:731 +msgid "Enter a new Job Code, or select a previous one" +msgstr "Defina uma nova etiqueta or selecione uma já presente" -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" -msgstr "Faltando 1 segundo aproximadamente" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:734 +msgid "Enter a new Job Code" +msgstr "Defina uma nova etiqueta" -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" -msgstr "Faltando %i segundos aproximadamente" +#: rapid/preferencesdialog.py:739 +msgid "Job Code:" +msgstr "Etiqueta:" -#: rapid/rapid.py:5851 -msgid "About 1 minute remaining" -msgstr "Faltando 1 minuto aproximadamente" +#: rapid/preferencesdialog.py:915 +msgid "Job Code" +msgstr "Etiqueta" -#. 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:5856 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Faltando %(minutes)i:%(seconds)02i minutos aproximadamente" +#: rapid/preferencesdialog.py:997 +msgid "Select a folder to download photos to" +msgstr "Selecione o diretório para baixar as fotos para" -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" +#: rapid/preferencesdialog.py:1015 +msgid "Select a folder to download videos to" +msgstr "Selecione o diretório para baixar os vídeos para" -#: rapid/rapid.py:5878 rapid/rapid.py:5890 +#: rapid/preferencesdialog.py:1106 #, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s downloaded" +msgid "Select a folder containing %(file_types)s" +msgstr "Escolha um diretório que contenha %(file_types)s" -#: rapid/rapid.py:5884 rapid/rapid.py:5896 +#: rapid/preferencesdialog.py:1128 #, python-format -msgid "%(filetype)s failed to download" +msgid "Select a folder in which to backup %(file_types)s" msgstr "" +"Escolha um diretório para o armazenamento de cópias de segurança de " +"%(file_types)s" -#: rapid/rapid.py:6070 -msgid "_Resume" +#. 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/preferencesdialog.py:1212 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" msgstr "" +"<i><b>Aviso:</b> As meta-Informações disponíveis são insuficientes para " +"gerar um nome de arquivo. Por favor, use outras opções de renomeação.</i>" -#: rapid/rapid.py:6073 -msgid "_Download All" +#: rapid/preferencesdialog.py:1263 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" msgstr "" +"<i><b>Aviso:</b> As meta-Informações disponíveis são insuficientes para " +"gerar nomes de subdiretórios. Por favor, use de outras opções de " +"nomeação.</i>" -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" -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/preferencesdialog.py:1266 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Exemplo: %s</i>" -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1356 +#, python-format +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." msgstr "" +"As preferências definidas para os subdiretórios de %(filetype)s são " +"inválidas e não poderão ser usadas.\n" +"Elas serão redefinidas para seus valores padrão." -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." -msgstr "" +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1642 +msgid "externaldrive1" +msgstr "disco_externo_1" -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." -msgstr "" +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1644 +msgid "externaldrive2" +msgstr "disco_externo_2" -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." -msgstr "" +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "Nova Iorque" -#: rapid/rapid.py:6422 -msgid "Goodbye" -msgstr "" +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manila" -#. 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:6433 -#, python-format -msgid "" -"display program information on the command line as the program runs " -"(default: %default)" -msgstr "" +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Praga" -#: rapid/rapid.py:6434 -msgid "display debugging information when run from the command line" -msgstr "" +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinque" -#: rapid/rapid.py:6435 -msgid "only output errors to the command line" -msgstr "" +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" -#. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6437 -msgid "list photo and video file extensions the program recognizes and exit" -msgstr "" +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Teerã" -#: rapid/rapid.py:6438 -msgid "reset all program settings and preferences and exit" -msgstr "" -"Restabelecer todas as configurações e preferências do programa e fechá-lo" +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" -#: rapid/rapid.py:6452 -msgid "Photos:" -msgstr "" +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Paris" -#: rapid/rapid.py:6452 -msgid "Videos:" -msgstr "" +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlim" -#: rapid/rapid.py:6457 -#, python-format -msgid "and %s" -msgstr "" +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sydney" -#: rapid/rapid.py:6465 -msgid "All settings and preferences have been reset" -msgstr "Todas as configurações e preferências foram restabelecidas" +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Budapeste" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" -msgstr "" +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Roma" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moscou" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Deli" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Varsóvia" -#: rapid/rapid.py:6474 -msgid "\n" -msgstr "\n" +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jacarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madri" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Estocolmo" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:343 +msgid "subfolder" +msgstr "subdiretório" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:341 +msgid "filename" +msgstr "nome de arquivo" -#. this application is already running -#: rapid/rapid.py:6498 +#: rapid/problemnotification.py:80 #, python-format -msgid "%s is already running" +msgid "Date time value %s appears invalid." msgstr "" -#: rapid/renamesubfolderprefs.py:192 -msgid "Date time" +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." msgstr "" -#: rapid/renamesubfolderprefs.py:193 -msgid "Text" +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." msgstr "" -#: rapid/renamesubfolderprefs.py:195 -msgid "Metadata" +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." msgstr "" -#: rapid/renamesubfolderprefs.py:196 -msgid "Sequences" +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" msgstr "" -#: rapid/renamesubfolderprefs.py:199 -msgid "Image date" +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" msgstr "" -#: rapid/renamesubfolderprefs.py:200 -msgid "Video date" +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" msgstr "" -#: rapid/renamesubfolderprefs.py:201 -msgid "Today" -msgstr "" +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "%(filetype)s já existe." -#: rapid/renamesubfolderprefs.py:202 -msgid "Yesterday" +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." msgstr "" -#. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 -msgid "Download time" +#: rapid/problemnotification.py:102 +#, python-format +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 -msgid "Name + extension" +#: rapid/problemnotification.py:103 +#, python-format +msgid "%(filetype)s was already downloaded" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:208 -msgid "Name" +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 -msgid "Extension" +#: rapid/problemnotification.py:108 +#, python-format +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 -msgid "Image number" +#: rapid/problemnotification.py:109 +#, python-format +msgid "There is no data with which to name the %(filetype)s." msgstr "" -#: rapid/renamesubfolderprefs.py:213 -msgid "Video number" +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 -msgid "Aperture" +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 -msgid "ISO" +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:219 -msgid "Exposure time" +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:221 -msgid "Focal length" +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:223 -msgid "Camera make" -msgstr "" +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "%s, " -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:225 -msgid "Camera model" +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:227 -msgid "Short camera model" +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:229 -msgid "Hyphenated short camera model" +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:231 -msgid "Serial number" +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:233 -msgid "Shutter count" +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:235 -msgid "Owner name" +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " msgstr "" -#: rapid/renamesubfolderprefs.py:236 -msgid "Codec" +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " msgstr "" -#: rapid/renamesubfolderprefs.py:237 -msgid "Width" +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." msgstr "" -#: rapid/renamesubfolderprefs.py:238 -msgid "Height" +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." msgstr "" -#: rapid/renamesubfolderprefs.py:239 -msgid "Length" +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." msgstr "" -#: rapid/renamesubfolderprefs.py:240 -msgid "Frames Per Second" +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 -msgid "Downloads today" +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:244 -msgid "Session number" +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:246 -msgid "Subfolder number" +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:248 -msgid "Stored number" +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:250 -msgid "Sequence letter" +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:252 -msgid "All digits" +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:254 -msgid "Last digit" +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:256 -msgid "Last 2 digits" +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:258 -msgid "Last 3 digits" +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:260 -msgid "Last 4 digits" +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." msgstr "" -#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:262 -msgid "Original Case" +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" msgstr "" -#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:264 -msgid "UPPERCASE" +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" msgstr "" -#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 -msgid "lowercase" +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" msgstr "" -#: rapid/renamesubfolderprefs.py:267 -msgid "One digit" +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" msgstr "" -#: rapid/renamesubfolderprefs.py:268 -msgid "Two digits" +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" msgstr "" -#: rapid/renamesubfolderprefs.py:269 -msgid "Three digits" +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" msgstr "" -#: rapid/renamesubfolderprefs.py:270 -msgid "Four digits" +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" msgstr "" -#: rapid/renamesubfolderprefs.py:271 -msgid "Five digits" +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" msgstr "" +"Foram detectadas fotografias de mesmo nome, mas de horários diferentes" -#: rapid/renamesubfolderprefs.py:272 -msgid "Six digits" +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" msgstr "" -#: rapid/renamesubfolderprefs.py:273 -msgid "Seven digits" +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 -msgid "Subseconds" +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 -msgid "YYYYMMDD" +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 -msgid "YYYY-MM-DD" +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:281 -msgid "YYMMDD" -msgstr "" +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 -msgid "YY-MM-DD" +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" + +#: rapid/subfolderfile.py:194 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" msgstr "" +"Origem: %(source)s\n" +"Destino: %(destination)s" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:285 -msgid "MMDDYYYY" +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" +msgstr "A foto já foi baixada" + +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" +msgstr "Origem: %(source)s" + +#: rapid/subfolderfile.py:339 +msgid "subfolder and filename" +msgstr "subdiretório e nome de arquivo" + +#: rapid/subfolderfile.py:377 +msgid "Failed to create download subfolder" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 -msgid "MMDDYY" +#: rapid/subfolderfile.py:378 +#, python-format +msgid "Path: %s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 -msgid "MMDD" +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 -msgid "DDMMYYYY" +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 -msgid "DDMMYY" +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 -msgid "YYYY" +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 -msgid "YY" +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 -msgid "MM" +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 -msgid "DD" +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 -msgid "HHMMSS" +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 -msgid "HHMM" +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 -msgid "HH-MM-SS" +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 -msgid "HH-MM" +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 -msgid "HH" +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 -msgid "MM (minutes)" +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 -msgid "SS" +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" msgstr "" -#: rapid/renamesubfolderprefs.py:800 -#, python-format -msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." msgstr "" -#: rapid/renamesubfolderprefs.py:807 -#, python-format -msgid "Preference value '%(value)s' is invalid" +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" msgstr "" -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" msgstr "" -#: rapid/renamesubfolderprefs.py:1524 -#, python-format -msgid "Subfolder preferences should not start with a %s" +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Limpar tarefas conluídas" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" msgstr "" -#: rapid/renamesubfolderprefs.py:1526 -#, python-format -msgid "Subfolder preferences should not end with a %s" +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "Registro de _Erros" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Arquivo" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "Aj_uda" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" msgstr "" -#: rapid/renamesubfolderprefs.py:1530 -#, python-format -msgid "Subfolder preferences should not contain two %s one after the other" +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "Fazer uma _doação..." + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Selecionar" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Traduzir este aplicativo..." + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" msgstr "" -#: rapid/glade3/rapid.glade.h:1 +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "E_xibir" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr "" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr "" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 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 +#: rapid/glade3/prefs.ui.h:20 msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:23 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.h:27 msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.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:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." msgstr "" -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1708,152 +1518,99 @@ msgid "" "reader.</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" msgstr "" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" msgstr "" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." msgstr "" -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "" -#: rapid/glade3/rapid.glade.h:62 -msgid "Overwrite" +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" msgstr "" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" +#: rapid/glade3/prefs.ui.h:58 +msgid "Overwrite" msgstr "" -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "" -#: rapid/glade3/rapid.glade.h:72 -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:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " "python." msgstr "" -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1862,13 +1619,13 @@ msgid "" "a folder in it with one of these names.</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 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:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." @@ -1876,44 +1633,44 @@ msgstr "" "Escolha se um caractere do nome de uma foto, vídeo ou diretório deverá ser " "omitido, caso o mesmo não seja suportado por outros sistemas operacionais." -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Iniciar a descarga após o início do programa" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" msgstr "Iniciar a descarga ao conectar o dispositivo" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Número acumulado:" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Omitir caracteres incompatíveis" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Sincronizar números seqüênciais em pares RAW-JPEG" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" msgstr "" "Desmontar ou ejetar o dispositivo após conclusão da tarefa de descarga" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Pasta de Vídeo" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" msgstr "Renomear Vídeo" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" msgstr "Nome da pasta para cópia de segurança de vídeos:" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." @@ -1921,7 +1678,7 @@ msgstr "" "Escolha como o programa deverá proceder caso ao copiar uma fotografia ou " "vídeo haja um arquivo de mesmo nome." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." @@ -1929,7 +1686,7 @@ msgstr "" "Escolha como o programa deverá proceder caso ao fazer uma cópia de segurança " "haja um arquivo de mesmo nome." -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." @@ -1938,77 +1695,318 @@ msgstr "" "uma cópia de segurança em vários locais diferentes, como, por exemplo, em " "discos rígidos externos." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Adicionar..." -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Limpar tarefas conluídas" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "" -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Dispositivo" +#~ msgid "_Type" +#~ msgstr "_Tipo" -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "Registro de _Erros" +#~ msgid "_Get Help Online..." +#~ msgstr "_Ajuda Online..." -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Arquivo" +#~ msgid "_Filename" +#~ msgstr "_Nome do arquivo" -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "_Nome do arquivo" +#~ msgid "_Path" +#~ msgstr "_Caminho" -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Ajuda Online..." +#~ msgid "_Preview" +#~ msgstr "Pre_visão" -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "Aj_uda" +#~ msgid "_Report a Problem..." +#~ msgstr "_Reportar um problema..." -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "Fazer uma _doação..." +#~ msgid "_Size" +#~ msgstr "Ta_manho" -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Caminho" +#~ msgid "_Device" +#~ msgstr "_Dispositivo" -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "Pre_visão" +#~ 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 "" +#~ "Pelo programa ser de uma versão mais avançada, algumas preferências são " +#~ "agora obsoletas e serão portanto restabelecidas em seus valores padrão." -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Reportar um problema..." +#~ msgid "Resetting to midnight.\n" +#~ msgstr "A restabelecer tempo em meia-noite.\n" -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Selecionar" +#~ msgid "Resetting to default values." +#~ msgstr "A restabelecer valores em seus padrões." -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "Ta_manho" +#~ msgid "Some preferences will be reset." +#~ msgstr "Algumas preferências serão restabelecidas." -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Traduzir este aplicativo..." +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "Algumas preferências são inválidas e serão portanto restabelecidas." -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Tipo" +#~ msgid "\n" +#~ msgstr "\n" -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "E_xibir" +#~ msgid " " +#~ msgstr " " + +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Valor de \"Descargas Hoje\" é inválido.\n" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Apesar da execução de descargas, o valor de \"descargas hoje\" não foi " +#~ "atualizado." + +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "Valor de \"começo do dia\" é inválido.\n" + +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Erro encontrado nas seguintes preferências:\n" + +#, python-format +#~ msgid "" +#~ "The %(filetype)s subfolder preferences had some unnecessary values removed." +#~ msgstr "" +#~ "Alguns valores foram julgados desnecessários e foram, conseqüentemente, " +#~ "removidos das prefências de subdiretórios de %(filetype)s." + +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Apesar da execução de descargas, o valor de \"número acumulado\" não foi " +#~ "atualizado." + +#~ msgid "The following download path could not be created:\n" +#~ msgstr "O seguinte destino de descarga não pôde ser criado:\n" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "" +#~ "Varredura do dispositivo completa: não foram encontrados %(filetypes)s em " +#~ "%(device)s" + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Varredura do dispositivo completa: %(number)s %(filetypes)s encontrados em " +#~ "%(device)s" + +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Por favor, tente novamente após revisar as preferências e reiniciar o " +#~ "programa." + +#~ msgid "There is an error in the program preferences." +#~ msgstr "Há um erro nas preferências do programa." + +#~ msgid "errors" +#~ msgstr "erros" + +#~ msgid "The device can now be safely removed" +#~ msgstr "O dispositivo poderá agora ser removido com segurança" + +#, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Origem: %s\n" + +#~ msgid "Error:" +#~ msgstr "Erro:" + +#~ msgid "Could not create temporary download directory" +#~ msgstr "O diretório temporário de descarga não pôde ser criado" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Destino: %s" + +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Dispositivo: %s\n" + +#~ msgid "No backups can occur" +#~ msgstr "Não foi possível a criação de cópias de segurança" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Diretório %s não pôde ser criado" + +#~ msgid "Backup path does not exist" +#~ msgstr "Diretório para armazenamento de cópias de segurança é inexistente" + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Origem: %(source)s\n" +#~ "Destino: %(destination)s\n" +#~ "%(problem)s" + +#, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "As cópias de segurança de %(file_type)s foram sobrescritas" + +#, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "Não foram feitas cópias de segurança de %(file_type)s em %(volume)s" + +#, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Já existem cópias de segurança de %(file_type)s" + +#~ msgid "Backing up error" +#~ msgstr "Erro ao criar cópias de segurança" + +#, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "Não foram feitas cópias de segurança de %(file_type)s" + +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "" +#~ "Um novo dia teve início - o número seqüencial \"descargas hoje\" foi " +#~ "restabelecido." + +#~ msgid "Please check your system and try again." +#~ msgstr "Por favor, tente novamente após uma revisão do sistema." + +#, python-format +#~ msgid "This device has no %(types_searched_for)s to download from." +#~ msgstr "" +#~ "Não há %(types_searched_for)s presentes nesse dispositivo, o que torna uma " +#~ "descarga desnecessária." + +#~ msgid "A backup location was not found" +#~ msgstr "" +#~ "Um dos locais destinado ao armazenamento de cópias de segurança não pôde ser " +#~ "encontrado" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Erro: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "%(file_type)s could not be backed up" +#~ msgstr "Não puderam ser feitas cópias de segurança de %(file_type)s." + +#, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "Não foram feitas cópias de segurança de %(file_type)s." + +#~ msgid "No suitable backup volume was found" +#~ msgstr "Não foi encontrado um volume adequado às cópias de seguraça." + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Erro: %(inst)s" + +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "Foram apagados(as) %(number)i %(filetypes)s do dispositivo" + +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "Este dispositivo ou partição será recordado para futuras descargas" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "" +#~ "Descarregar arquivos diretamente de uma câmera pode ser muito problemático" + +#~ msgid "" +#~ "Downloading from a card reader always works and is generally much faster. It " +#~ "is strongly recommended to use a card reader." +#~ msgstr "" +#~ "O uso de leitores de cartão é recomendado. Eles funcionam sempre e são " +#~ "geralmente mais rápidos." + +#~ msgid "_Show this message again" +#~ msgstr "_Exibir esta mensagem novamente" + +#~ msgid "Job Code entered" +#~ msgstr "Etiqueta definida" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "Este dispositivo ou partição será rejeitado para futuras descargas" + +#~ msgid "Job Code not entered" +#~ msgstr "Etiqueta não definida" + +#~ msgid "Path" +#~ msgstr "Caminho" + +#~ msgid "Date" +#~ msgstr "Data" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s não foi descarregado(a)." + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s foi descarregado(a) com ressalvas." + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s foi descarregado(a) com êxito." + +#~ msgid "File" +#~ msgstr "Arquivo" + +#~ msgid "Type" +#~ msgstr "Tipo" + +#, python-format +#~ msgid "%(filetype)s was downloaded but there were problems backing up" +#~ msgstr "" +#~ "%(filetype)s foi descarregado(a), mas houve problemas durante a criação de " +#~ "cópias de segurança." + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s está proto para a descarga" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s será descarregado(a) com ressalvas" + +#, python-format +#~ msgid "%(filetype)s is about to be downloaded" +#~ msgstr "%(filetype)s será descarregado" + +#, python-format +#~ msgid "%(filetype)s was neither downloaded nor backed up" +#~ msgstr "" +#~ "%(filetype)s não foi descarregado(a), nem cópias de segurança foram criadas." + +#~ msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#~ msgstr "" +#~ "Defina uma nova etiqueta e confirme com a tecla Enter, ou selecione uma " +#~ "etiqueta já existente" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s não pode ser descarregado(a)." #~ msgid "Preview" #~ msgstr "Previsão" +#, python-format +#~ msgid "%(free)s available" +#~ msgstr "%(free)s disponíveis ao uso" + #~ msgid "" #~ "The subfolder preferences entered are invalid and cannot be used.\n" #~ "They will be reset to their default values." @@ -2176,6 +2174,51 @@ msgstr "E_xibir" #~ "Imagem: %(image)s\n" #~ "Problema: %(problem)s" +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Redefinindo valor para zero.\n" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Diretório de destino não pôde ser criado: %(directory)s\n" + +#, python-format +#~ msgid "Attempting to download %s files" +#~ msgstr "Tentando baixar %s arquivos" + +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Não foi possível apagar as fotos ou vídeos do dispositivo" + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Foto: %(source)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Foto: %(source)s\n" +#~ "Erro: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s foi rejeitado como um dispositivo de transferência" + +#~ msgid "Downloading From Cameras" +#~ msgstr "Baixando das câmeras" + +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Transferência foi iniciada em %s" + +#, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Transferência concluída de %s" + +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s selecionado para transferência de" + #~ msgid "Thumbnail cannot be displayed" #~ msgstr "A miniatura não pode ser exibida" @@ -2207,12 +2250,174 @@ msgstr "E_xibir" #~ msgid "Image already exists" #~ msgstr "Imagem já existe" +#~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "As preferências do programa parecem ser válidas, mas por favor verifique-los " +#~ "para garantir o funcionamento correto." + +#~ msgid "" +#~ "A newer version of this program was previously run on this computer.\n" +#~ "\n" +#~ msgstr "" +#~ "Uma nova versão deste programa foi executado anteriormente nesse " +#~ "computador.\n" +#~ "\n" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "A partir de downloads que foram à espera de um código de trabalho" + #~ msgid "Enter a new job code." #~ msgstr "Introduza um código novo emprego." +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Solicitação de se usar %s" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Já foi solicitado o Trabalho Código, não perguntar de novo" + #~ msgid "Enter a new job code, or select a previous one." #~ msgstr "" #~ "Introduza um código novo emprego, ou selecione uma pesquisa anterior." +#~ msgid "Starting downloads" +#~ msgstr "Iniciando downloads" + #~ msgid "Should this device or partition be used to download images from?" #~ msgstr "este dispositivo ou partição deve ser usado para baixar imagens?" + +#~ msgid "Prompting for Job Code" +#~ msgstr "Solicitando o código de trabalho" + +#, python-format +#~ msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#~ msgstr "A %(file_type)s Pasta de Download existe mas não pode ser escrita.\n" + +#, python-format +#~ msgid "The %(file_type)s Download Folder does not exist.\n" +#~ msgstr "A %(file_type)s Pasta de Download não existe.\n" + +#~ msgid "Problem with Download Folders" +#~ msgstr "Problemas com as Pastas de Download" + +#~ msgid "" +#~ "Sorry, problems were encountered with your download folders. Please fix the " +#~ "problems or modify the preferences.\n" +#~ "\n" +#~ msgstr "" +#~ "Desculpe, alguns problemas foram encontrados com as suas pastas de download. " +#~ "Por favor, corrija os problemas ou modifique as preferências.\n" +#~ "\n" + +#~ msgid "Displaying warning about downloading directly from camera" +#~ msgstr "Resultados de aviso sobre o download diretamente da câmera" + +#, python-format +#~ msgid "Creating photo download folder %(folder)s" +#~ msgstr "Criando pasta de download de fotos %(folder)s" + +#~ msgid "Problem with Download Folder" +#~ msgstr "Problema com a Pasta de Download" + +#, python-format +#~ msgid "" +#~ "Sorry, this device location does not exist:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Please resolve the problem, or modify your preferences." +#~ msgstr "" +#~ "Desculpe, esta localização do dispositivo não existe:\n" +#~ "%(path)s" + +#~ msgid "Problem with Device Location Folder" +#~ msgstr "Problema com o dispositivo local da pasta" + +#~ msgid "Warning:" +#~ msgstr "Atenção:" + +#~ msgid "No preferences needed to be changed." +#~ msgstr "Nenhuma preferência precisou ser mudada." + +#~ 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 versão do programa utiliza diferentes preferências que a versão antiga. " +#~ "Suas preferências foram atualizadas.\n" +#~ "\n" +#~ "Por favor verifique-los para garantir o funcionamento correto." + +#~ msgid "Preferences were modified." +#~ msgstr "As preferências foram modificadas." + +#~ msgid "" +#~ "This version of the program is newer than the previously run version. " +#~ "Checking preferences." +#~ msgstr "" +#~ "Esta versão do programa é mais recente que a versão anteriormente executada. " +#~ "Verificar preferências." + +#~ msgid "Problem using pynotify." +#~ msgstr "Problema com pynotify." + +#, python-format +#~ msgid "Failed to create default video download folder %(folder)s" +#~ msgstr "Falha ao criar pasta padrão de download de vídeo %(folder)s" + +#, python-format +#~ msgid "Creating video download folder %(folder)s" +#~ msgstr "Criando pasta de download de vídeo %(folder)s" + +#, python-format +#~ msgid "Failed to create default photo download folder %(folder)s" +#~ msgstr "Falha ao criar pasta padrão de download de fotos %(folder)s" + +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Falha ao receber recursos do servidor pynotify." + +#~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Atenção: servidor de notificações ambiente desktop está configurado " +#~ "incorretamente." + +#~ msgid "Using manually specified path" +#~ msgstr "Usando o caminho especificado manualmente" + +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Dispositivo %(device)s (%(path)s ignorado" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Detectado %(device)s com o caminho %(path)s" + +#~ msgid "No backup devices detected" +#~ msgstr "Nenhum dispositivo de backup detectado" + +#~ msgid "Automatically start download is false" +#~ msgstr "Iniciar download automaticamente é falso" + +#~ msgid "Automatically start download is true" +#~ msgstr "Iniciar download automaticamente é verdadeiro" + +#~ msgid "and" +#~ msgstr "e" + +#~ msgid "Using backup device" +#~ msgstr "Usando o dispositivo de backup" + +#~ msgid "Using backup devices" +#~ msgstr "Usando dispositivos de backup" + +#, python-format +#~ msgid "Warning: backup device %(device)s is currently being downloaded from" +#~ msgstr "" +#~ "Atenção: dispositivo de backup %(device)s atualmente está sendo baixado" + +#~ msgid "D_ownload Selected" +#~ msgstr "D_ownload selecionados" diff --git a/po/rapid-photo-downloader.pot b/po/rapid-photo-downloader.pot index 5f1daf6..fc82f8e 100644 --- a/po/rapid-photo-downloader.pot +++ b/po/rapid-photo-downloader.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" +"POT-Creation-Date: 2011-04-21 01:12-0500\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" @@ -18,1608 +18,1503 @@ msgstr "" "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:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:105 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "" - -#: rapid/rapid.py:463 -msgid "Sydney" +#: rapid/rapid.py:110 +#, python-format +msgid "" +"%(date)s\n" +"%(time)s" msgstr "" -#: rapid/rapid.py:464 -msgid "Budapest" +#: rapid/rapid.py:112 +#, python-format +msgid "%(date)s %(time)s" msgstr "" -#: rapid/rapid.py:464 -msgid "Rome" +#: rapid/rapid.py:115 +#, python-format +msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "" -#: rapid/rapid.py:464 -msgid "Moscow" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:149 +msgid "Device" msgstr "" -#: rapid/rapid.py:464 -msgid "Delhi" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:166 +msgid "Size" msgstr "" -#: rapid/rapid.py:464 -msgid "Warsaw" +#: rapid/rapid.py:169 +msgid "Download Progress" msgstr "" -#: rapid/rapid.py:465 -msgid "Jakarta" +#: rapid/rapid.py:315 +#, python-format +msgid "%(device)s did not unmount" msgstr "" -#: rapid/rapid.py:465 -msgid "Madrid" +#. This refers to when a device like a hard drive is having its contents scanned, +#. looking for photos or videos. It is visible initially in the progress bar for each device +#. (which normally holds "x photos and videos"). +#. It maybe displayed only briefly if the contents of the device being scanned is small. +#: rapid/rapid.py:1154 +msgid "scanning..." msgstr "" -#: rapid/rapid.py:465 -msgid "Stockholm" +#: rapid/rapid.py:1969 +msgid "Download" msgstr "" -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" +#: rapid/rapid.py:1972 +msgid "Pause" msgstr "" -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" +#: rapid/rapid.py:2075 +#, python-format +msgid "" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" msgstr "" -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" +#: rapid/rapid.py:2078 +#, python-format +msgid "" +"This download folder is invalid:\n" +"%s" msgstr "" -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" +#: rapid/rapid.py:2079 +msgid "Download cannot proceed" msgstr "" -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" +#: rapid/rapid.py:2360 +msgid "About 1 second remaining" msgstr "" -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" +#: rapid/rapid.py:2362 +#, python-format +msgid "About %i seconds remaining" msgstr "" -#: rapid/rapid.py:609 -msgid "Resetting to default values." +#: rapid/rapid.py:2364 +msgid "About 1 minute remaining" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" +#. 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:2369 +#, python-format +msgid "About %(minutes)i:%(seconds)02i minutes remaining" msgstr "" -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" +#: rapid/rapid.py:2381 rapid/preferencesdialog.py:822 rapid/rpdfile.py:110 +msgid "photos and videos" msgstr "" -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" +#: rapid/rapid.py:2383 rapid/rpdfile.py:112 +msgid "photos or videos" msgstr "" -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" +#: rapid/rapid.py:2386 rapid/rapid.py:2929 rapid/rpdfile.py:115 +msgid "videos" msgstr "" -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" +#: rapid/rapid.py:2388 rapid/preferencesdialog.py:1373 rapid/rpdfile.py:117 +#: rapid/rpdfile.py:270 +msgid "video" msgstr "" -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 +#: rapid/rapid.py:2391 rapid/rapid.py:2927 rapid/preferencesdialog.py:824 +#: rapid/rpdfile.py:120 msgid "photos" msgstr "" -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" +#. check subfolder preferences for bad values +#: rapid/rapid.py:2393 rapid/preferencesdialog.py:1372 rapid/rpdfile.py:122 +#: rapid/rpdfile.py:250 +msgid "photo" msgstr "" -#: rapid/rapid.py:1055 +#: rapid/rapid.py:2420 #, python-format -msgid "Select a folder containing %(file_types)s" +msgid "%(noFiles)s %(filetypes)s downloaded" msgstr "" -#: rapid/rapid.py:1077 +#: rapid/rapid.py:2424 #, python-format -msgid "Select a folder in which to backup %(file_types)s" +msgid "%(noFiles)s %(filetypes)s failed to download" 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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" +#: rapid/rapid.py:2427 rapid/rapid.py:2479 +msgid "warnings" msgstr "" -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" +#: rapid/rapid.py:2436 +msgid "All downloads complete" 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:1198 +#: rapid/rapid.py:2442 rapid/rapid.py:2451 rapid/rapid.py:2460 +#: rapid/rapid.py:2469 rapid/rapid.py:2477 #, python-format -msgid "<i>Example: %s</i>" -msgstr "" - -#: rapid/rapid.py:1224 -msgid "Downloads today value not updated, as a download is currently occurring" -msgstr "" - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" +msgid "%(number)s %(numberdownloaded)s" msgstr "" -#: rapid/rapid.py:1270 +#: rapid/rapid.py:2444 rapid/rapid.py:2462 #, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." +msgid "%(filetype)s downloaded" msgstr "" -#. Preferences list is now empty -#: rapid/rapid.py:1275 +#: rapid/rapid.py:2453 rapid/rapid.py:2471 #, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" +msgid "%(filetype)s failed to download" msgstr "" -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" +#. e.g.: 3 of 205 photos and videos (202 remaining) +#: rapid/rapid.py:2510 +#, python-format +msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" msgstr "" -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -msgid "externaldrive1" +#. e.g.: 205 of 205 photos and videos +#: rapid/rapid.py:2517 +#, python-format +msgid "%(number)s of %(total)s %(filetypes)s" msgstr "" -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1529 -msgid "externaldrive2" +#: rapid/rapid.py:2897 +msgid "and" msgstr "" -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" +#: rapid/rapid.py:2902 +msgid "Using backup devices" msgstr "" -#: rapid/rapid.py:1556 -msgid "videos" +#: rapid/rapid.py:2904 +msgid "Using backup device" msgstr "" -#: rapid/rapid.py:1568 -#, python-format -msgid "" -"%(date)s\n" -"%(time)s" +#: rapid/rapid.py:2906 +msgid "No backup devices detected" msgstr "" -#: rapid/rapid.py:1570 -#, python-format -msgid "%(date)s %(time)s" +#: rapid/rapid.py:2933 +msgid "Free space:" msgstr "" -#: rapid/rapid.py:1573 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2945 #, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgid "(%(file_type)s)" msgstr "" -#: rapid/rapid.py:1580 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2949 #, python-format -msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "" - -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" +msgid "%(free)s %(file_type)s" msgstr "" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2954 +msgid "; " msgstr "" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2959 +msgid "." msgstr "" -#. This refers to when a device like a hard drive is having its contents scanned, -#. looking for photos or videos. It is visible initially in the progress bar for each device -#. (which normally holds "x photos and videos"). -#. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 -msgid "scanning..." +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2965 +#, python-format +msgid "%(free)s free" msgstr "" -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" +#. user manually specified backup location +#: rapid/rapid.py:2971 +#, python-format +msgid "Backing up to %(path)s" msgstr "" -#: rapid/rapid.py:1819 +#: rapid/rapid.py:2976 #, python-format -msgid "%(path)s: " +msgid "%(freespace)s. %(backuppaths)s." msgstr "" -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 -msgid "Download cannot proceed" +#: rapid/rapid.py:3005 +msgid "Program preferences are invalid" msgstr "" -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." +#: rapid/rapid.py:3110 rapid/rpdfile.py:251 +msgid "Photo" msgstr "" -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." +#: rapid/rapid.py:3112 rapid/rpdfile.py:271 +msgid "Video" 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 +#: rapid/rapid.py:3121 #, python-format -msgid "%(number)s %(filetypes)s" +msgid "%(file_type)s download folder does not exist" 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 photos 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:2019 +#: rapid/rapid.py:3123 rapid/rapid.py:3137 rapid/rapid.py:3150 #, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +msgid "Folder: %s" msgstr "" -#: rapid/rapid.py:2026 +#: rapid/rapid.py:3135 #, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" +msgid "%(file_type)s download folder is invalid" 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:2047 -msgid "The device can now be safely removed" +#: rapid/rapid.py:3148 +#, python-format +msgid "%(file_type)s download folder is not writable" msgstr "" -#: rapid/rapid.py:2053 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" +#: rapid/rapid.py:3226 +msgid "Thumbnails" msgstr "" -#: rapid/rapid.py:2056 +#. 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:3273 #, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" +msgid "" +"display program information on the command line as the program runs " +"(default: %default)" msgstr "" -#: rapid/rapid.py:2059 rapid/rapid.py:5901 -msgid "warnings" +#: rapid/rapid.py:3274 +msgid "display debugging information when run from the command line" msgstr "" -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" +#: rapid/rapid.py:3275 +msgid "only output errors to the command line" msgstr "" -#: rapid/rapid.py:2091 -#, python-format -msgid "Source: %s\n" +#. image file extensions are recognized RAW files plus TIFF and JPG +#: rapid/rapid.py:3277 +msgid "list photo and video file extensions the program recognizes and exit" msgstr "" -#: rapid/rapid.py:2093 -#, python-format -msgid "Device: %s\n" +#: rapid/rapid.py:3278 +msgid "reset all program settings and preferences and exit" msgstr "" -#: rapid/rapid.py:2094 -#, python-format -msgid "Destination: %s" +#: rapid/rapid.py:3291 +msgid "Photos:" msgstr "" -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" +#: rapid/rapid.py:3291 +msgid "Videos:" msgstr "" -#: rapid/rapid.py:2098 -msgid "Error:" +#: rapid/rapid.py:3296 +#, python-format +msgid "and %s" msgstr "" -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" +#: rapid/rapid.py:3304 +msgid "All settings and preferences have been reset" msgstr "" -#: rapid/rapid.py:2123 -#, python-format -msgid "The path %s could not be created" +#: rapid/rapid.py:3313 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." msgstr "" -#: rapid/rapid.py:2124 -msgid "No backups can occur" +#: rapid/backupfile.py:139 rapid/backupfile.py:162 +msgid "Backing up error" msgstr "" -#: rapid/rapid.py:2153 +#: rapid/backupfile.py:141 #, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +msgid "Destination directory could not be created: %(directory)s\n" msgstr "" -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 +#: rapid/backupfile.py:143 rapid/backupfile.py:164 rapid/subfolderfile.py:194 #, python-format msgid "" "Source: %(source)s\n" "Destination: %(destination)s" msgstr "" -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "" - -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" - -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" -msgstr "" - -#: rapid/rapid.py:2260 rapid/rapid.py:2659 -#, python-format -msgid "Source: %(source)s" -msgstr "" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "" - -#: rapid/rapid.py:2529 +#: rapid/backupfile.py:146 rapid/backupfile.py:166 #, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "" - -#: rapid/rapid.py:2533 -#, python-format -msgid "Backup %(file_type)s overwritten" +msgid "Error: %(inst)s" msgstr "" -#: rapid/rapid.py:2537 +#: rapid/copyfiles.py:143 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:332 rapid/subfolderfile.py:350 #, python-format -msgid "%(file_type)s not backed up to %(volume)s" +msgid "" +"%(problem)s\n" +"File: %(file)s" msgstr "" -#: rapid/rapid.py:2539 -#, python-format -msgid "%(file_type)s not backed up" +#: rapid/device.py:79 +msgid "Device Detected" msgstr "" -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" msgstr "" -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" msgstr "" -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" +#: rapid/downloadtracker.py:246 +msgid "MB/s" msgstr "" -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 -#, python-format -msgid "The %(file_type)s was not backed up." +#: rapid/generatenameconfig.py:143 +msgid "Date time" msgstr "" -#: rapid/rapid.py:2595 rapid/rapid.py:2645 -#, python-format -msgid "Error: %(errno)s %(strerror)s" +#: rapid/generatenameconfig.py:144 +msgid "Text" msgstr "" -#: rapid/rapid.py:2658 -#, python-format -msgid "%(file_type)s could not be backed up" +#: rapid/generatenameconfig.py:145 +msgid "Filename" msgstr "" -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" +#: rapid/generatenameconfig.py:146 +msgid "Metadata" msgstr "" -#: rapid/rapid.py:2663 -msgid "A backup location was not found" +#: rapid/generatenameconfig.py:147 +msgid "Sequences" msgstr "" -#: rapid/rapid.py:2717 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:549 +msgid "Job code" msgstr "" -#: rapid/rapid.py:2813 -#, python-format -msgid "Download has started from %s" +#: rapid/generatenameconfig.py:150 +msgid "Image date" msgstr "" -#: rapid/rapid.py:2817 -#, python-format -msgid "Attempting to download %s files" +#: rapid/generatenameconfig.py:151 +msgid "Video date" msgstr "" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s" +#: rapid/generatenameconfig.py:152 +msgid "Today" msgstr "" -#: rapid/rapid.py:2913 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" +#: rapid/generatenameconfig.py:153 +msgid "Yesterday" msgstr "" -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" +#. Translators: Download time is the time and date that the download started (when the user clicked the Download button) +#: rapid/generatenameconfig.py:155 +msgid "Download time" msgstr "" -#: rapid/rapid.py:2939 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:157 +msgid "Name + extension" msgstr "" -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:159 +msgid "Name" msgstr "" -#: rapid/rapid.py:2945 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:161 +msgid "Extension" msgstr "" -#: rapid/rapid.py:2958 -#, python-format -msgid "Download complete from %s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:163 +msgid "Image number" msgstr "" -#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. -#: rapid/rapid.py:3073 rapid/rapid.py:3542 -msgid "Device" +#: rapid/generatenameconfig.py:164 +msgid "Video number" msgstr "" -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:166 +msgid "Aperture" msgstr "" -#: rapid/rapid.py:3081 -msgid "Download Progress" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:168 +msgid "ISO" msgstr "" -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:170 +msgid "Exposure time" msgstr "" -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:172 +msgid "Focal length" msgstr "" -#: rapid/rapid.py:3176 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:174 +msgid "Camera make" msgstr "" -#: rapid/rapid.py:3190 -msgid "_Show this message again" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:176 +msgid "Camera model" msgstr "" -#: rapid/rapid.py:3225 -msgid "Device Detected" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:178 +msgid "Short camera model" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "" -"Should this device or partition be used to download photos or videos from?" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:180 +msgid "Hyphenated short camera model" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 -msgid "_Remember this choice" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:182 +msgid "Serial number" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 -#, python-format -msgid "%s selected for downloading from" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:184 +msgid "Shutter count" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata +#: rapid/generatenameconfig.py:186 +msgid "Owner name" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" +#: rapid/generatenameconfig.py:187 +msgid "Codec" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" +#: rapid/generatenameconfig.py:188 +msgid "Width" msgstr "" -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" +#: rapid/generatenameconfig.py:189 +msgid "Height" msgstr "" -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" +#: rapid/generatenameconfig.py:190 +msgid "Length" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" +#: rapid/generatenameconfig.py:191 +msgid "Frames Per Second" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:193 +msgid "Downloads today" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:195 +msgid "Session number" msgstr "" -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:197 +msgid "Subfolder number" msgstr "" -#: rapid/rapid.py:3425 -msgid "Job Code entered" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers +#: rapid/generatenameconfig.py:199 +msgid "Stored number" msgstr "" -#: rapid/rapid.py:3427 -msgid "Job Code not entered" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters +#: rapid/generatenameconfig.py:201 +msgid "Sequence letter" msgstr "" -#: rapid/rapid.py:3477 -msgid "Status" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:203 +msgid "All digits" msgstr "" -#: rapid/rapid.py:3485 -msgid "Type" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:205 +msgid "Last digit" msgstr "" -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:207 +msgid "Last 2 digits" msgstr "" -#: rapid/rapid.py:3496 -msgid "File" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:209 +msgid "Last 3 digits" msgstr "" -#: rapid/rapid.py:3511 -msgid "Job Code" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename +#: rapid/generatenameconfig.py:211 +msgid "Last 4 digits" msgstr "" -#: rapid/rapid.py:3521 -msgid "Date" +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/generatenameconfig.py:213 +msgid "Original Case" msgstr "" -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/generatenameconfig.py:215 +msgid "UPPERCASE" msgstr "" -#: rapid/rapid.py:3564 -msgid "Path" +#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization +#: rapid/generatenameconfig.py:217 +msgid "lowercase" msgstr "" -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" +#: rapid/generatenameconfig.py:218 +msgid "One digit" msgstr "" -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" +#: rapid/generatenameconfig.py:219 +msgid "Two digits" msgstr "" -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" +#: rapid/generatenameconfig.py:220 +msgid "Three digits" msgstr "" -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" +#: rapid/generatenameconfig.py:221 +msgid "Four digits" msgstr "" -#: rapid/rapid.py:3982 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" +#: rapid/generatenameconfig.py:222 +msgid "Five digits" msgstr "" -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" +#: rapid/generatenameconfig.py:223 +msgid "Six digits" msgstr "" -#: rapid/rapid.py:3986 -#, python-format -msgid "%(filetype)s is about to be downloaded" +#: rapid/generatenameconfig.py:224 +msgid "Seven digits" msgstr "" -#: rapid/rapid.py:3988 -#, python-format -msgid "%(filetype)s will be downloaded with warnings" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:226 +msgid "Subseconds" msgstr "" -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:228 +msgid "YYYYMMDD" msgstr "" -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:230 +msgid "YYYY-MM-DD" msgstr "" -#: rapid/rapid.py:5034 -#, python-format -msgid "%(free)s available" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:232 +msgid "YYMMDD" msgstr "" -#. user manually specified backup location -#: rapid/rapid.py:5040 -#, python-format -msgid "Backing up to %(path)s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:234 +msgid "YY-MM-DD" msgstr "" -#: rapid/rapid.py:5045 -#, python-format -msgid "%(freespace)s. %(backuppaths)s." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:236 +msgid "MMDDYYYY" msgstr "" -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:238 +msgid "MMDDYY" msgstr "" -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:240 +msgid "MMDD" msgstr "" -#: rapid/rapid.py:5067 -msgid "Video" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:242 +msgid "DDMMYYYY" msgstr "" -#: rapid/rapid.py:5074 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:244 +msgid "DDMMYY" msgstr "" -#: rapid/rapid.py:5083 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:246 +msgid "YYYY" msgstr "" -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:248 +msgid "YY" msgstr "" -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:250 +msgid "MM" msgstr "" -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:252 +msgid "DD" msgstr "" -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:254 +msgid "HHMMSS" msgstr "" -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:256 +msgid "HHMM" msgstr "" -#: rapid/rapid.py:5149 -#, python-format -msgid "Prompting whether to use %s" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:258 +msgid "HH-MM-SS" msgstr "" -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:260 +msgid "HH-MM" msgstr "" -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:262 +msgid "HH" msgstr "" -#: rapid/rapid.py:5197 -msgid "Starting downloads" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:264 +msgid "MM (minutes)" msgstr "" -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime +#: rapid/generatenameconfig.py:266 +msgid "SS" msgstr "" -#: rapid/rapid.py:5248 +#: rapid/preferencesdialog.py:370 #, python-format -msgid "Creating photo download folder %(folder)s" +msgid "Subfolder preferences should not start with a %s" msgstr "" -#: rapid/rapid.py:5253 +#: rapid/preferencesdialog.py:372 #, python-format -msgid "Failed to create default photo download folder %(folder)s" +msgid "Subfolder preferences should not end with a %s" msgstr "" -#: rapid/rapid.py:5257 +#: rapid/preferencesdialog.py:376 #, python-format -msgid "Creating video download folder %(folder)s" +msgid "Subfolder preferences should not contain two %s one after the other" msgstr "" -#: rapid/rapid.py:5262 -#, python-format -msgid "Failed to create default video download folder %(folder)s" +#: rapid/preferencesdialog.py:389 rapid/preferencesdialog.py:672 +msgid "Remove all Job Codes?" msgstr "" -#: rapid/rapid.py:5287 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" +#: rapid/preferencesdialog.py:406 rapid/preferencesdialog.py:689 +msgid "Should all Job Codes be removed?" msgstr "" -#: rapid/rapid.py:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." +#: rapid/preferencesdialog.py:436 +msgid "Error in Photo Rename preferences" msgstr "" -#: rapid/rapid.py:5291 -msgid "Sorry, some preferences are invalid and will be reset." +#: rapid/preferencesdialog.py:617 +msgid "Error in Video Rename preferences" msgstr "" -#: rapid/rapid.py:5292 -msgid "Warning:" +#: rapid/preferencesdialog.py:638 +msgid "Error in Photo Download Subfolders preferences" msgstr "" -#: rapid/rapid.py:5297 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." +#: rapid/preferencesdialog.py:655 +msgid "Error in Video Download Subfolders preferences" msgstr "" -#: rapid/rapid.py:5304 -msgid "Preferences were modified." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:714 +msgid "Enter a Job Code" msgstr "" -#: rapid/rapid.py:5305 -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." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:731 +msgid "Enter a new Job Code, or select a previous one" msgstr "" -#: rapid/rapid.py:5309 -msgid "No preferences needed to be changed." +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:734 +msgid "Enter a new Job Code" msgstr "" -#: rapid/rapid.py:5311 -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." +#: rapid/preferencesdialog.py:739 +msgid "Job Code:" msgstr "" -#: rapid/rapid.py:5321 -msgid "Problem using pynotify." +#: rapid/preferencesdialog.py:915 +msgid "Job Code" msgstr "" -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." +#: rapid/preferencesdialog.py:997 +msgid "Select a folder to download photos to" msgstr "" -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." +#: rapid/preferencesdialog.py:1015 +msgid "Select a folder to download videos to" msgstr "" -#: rapid/rapid.py:5396 -msgid "and" +#: rapid/preferencesdialog.py:1106 +#, python-format +msgid "Select a folder containing %(file_types)s" msgstr "" -#: rapid/rapid.py:5401 -msgid "Using backup devices" +#: rapid/preferencesdialog.py:1128 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" msgstr "" -#: rapid/rapid.py:5403 -msgid "Using backup device" +#. 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/preferencesdialog.py:1214 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" msgstr "" -#: rapid/rapid.py:5405 -msgid "No backup devices detected" +#: rapid/preferencesdialog.py:1265 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" msgstr "" -#: rapid/rapid.py:5455 rapid/rapid.py:5617 +#. 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/preferencesdialog.py:1268 #, python-format -msgid "Device %(device)s (%(path)s) ignored" +msgid "<i>Example: %s</i>" msgstr "" -#: rapid/rapid.py:5576 +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1358 #, python-format -msgid "Detected %(device)s with path %(path)s" +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." msgstr "" -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1644 +msgid "externaldrive1" msgstr "" -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1646 +msgid "externaldrive2" msgstr "" -#: rapid/rapid.py:5635 -msgid "Using manually specified path" +#: rapid/prefsrapid.py:122 +msgid "New York" msgstr "" -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" +#: rapid/prefsrapid.py:123 +msgid "Manila" msgstr "" -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" +#: rapid/prefsrapid.py:123 +msgid "Prague" msgstr "" -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" +#: rapid/prefsrapid.py:123 +msgid "Helsinki" msgstr "" -#: rapid/rapid.py:5837 -msgid "MB/s" +#: rapid/prefsrapid.py:123 +msgid "Wellington" msgstr "" -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" +#: rapid/prefsrapid.py:124 +msgid "Tehran" msgstr "" -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" +#: rapid/prefsrapid.py:124 +msgid "Kampala" msgstr "" -#: rapid/rapid.py:5851 -msgid "About 1 minute remaining" +#: rapid/prefsrapid.py:124 +msgid "Paris" 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:5856 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" +#: rapid/prefsrapid.py:124 +msgid "Berlin" msgstr "" -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" +#: rapid/prefsrapid.py:124 +msgid "Sydney" msgstr "" -#: rapid/rapid.py:5878 rapid/rapid.py:5890 -#, python-format -msgid "%(filetype)s downloaded" +#: rapid/prefsrapid.py:125 +msgid "Budapest" msgstr "" -#: rapid/rapid.py:5884 rapid/rapid.py:5896 -#, python-format -msgid "%(filetype)s failed to download" +#: rapid/prefsrapid.py:125 +msgid "Rome" msgstr "" -#: rapid/rapid.py:6070 -msgid "_Resume" +#: rapid/prefsrapid.py:125 +msgid "Moscow" msgstr "" -#: rapid/rapid.py:6073 -msgid "_Download All" +#: rapid/prefsrapid.py:125 +msgid "Delhi" msgstr "" -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" +#: rapid/prefsrapid.py:125 +msgid "Warsaw" msgstr "" -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." +#: rapid/prefsrapid.py:126 +msgid "Jakarta" msgstr "" -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." +#: rapid/prefsrapid.py:126 +msgid "Madrid" msgstr "" -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." +#: rapid/prefsrapid.py:126 +msgid "Stockholm" msgstr "" -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:343 +msgid "subfolder" msgstr "" -#: rapid/rapid.py:6422 -msgid "Goodbye" +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:341 +msgid "filename" 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:6433 +#: rapid/problemnotification.py:80 #, python-format -msgid "" -"display program information on the command line as the program runs " -"(default: %default)" +msgid "Date time value %s appears invalid." msgstr "" -#: rapid/rapid.py:6434 -msgid "display debugging information when run from the command line" +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." msgstr "" -#: rapid/rapid.py:6435 -msgid "only output errors to the command line" +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." msgstr "" -#. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6437 -msgid "list photo and video file extensions the program recognizes and exit" +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." msgstr "" -#: rapid/rapid.py:6438 -msgid "reset all program settings and preferences and exit" +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" msgstr "" -#: rapid/rapid.py:6452 -msgid "Photos:" +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" msgstr "" -#: rapid/rapid.py:6452 -msgid "Videos:" +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" msgstr "" -#: rapid/rapid.py:6457 +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 #, python-format -msgid "and %s" +msgid "%(filetype)s already exists" msgstr "" -#: rapid/rapid.py:6465 -msgid "All settings and preferences have been reset" +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." msgstr "" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" +#: rapid/problemnotification.py:102 +#, python-format +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." msgstr "" -#: rapid/rapid.py:6474 -msgid "\n" +#: rapid/problemnotification.py:103 +#, python-format +msgid "%(filetype)s was already downloaded" msgstr "" -#. this application is already running -#: rapid/rapid.py:6498 +#: rapid/problemnotification.py:107 #, python-format -msgid "%s is already running" +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." msgstr "" -#: rapid/renamesubfolderprefs.py:192 -msgid "Date time" +#: rapid/problemnotification.py:108 +#, python-format +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." msgstr "" -#: rapid/renamesubfolderprefs.py:193 -msgid "Text" +#: rapid/problemnotification.py:109 +#, python-format +msgid "There is no data with which to name the %(filetype)s." msgstr "" -#: rapid/renamesubfolderprefs.py:195 -msgid "Metadata" +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" msgstr "" -#: rapid/renamesubfolderprefs.py:196 -msgid "Sequences" +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." msgstr "" -#: rapid/renamesubfolderprefs.py:199 -msgid "Image date" +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." msgstr "" -#: rapid/renamesubfolderprefs.py:200 -msgid "Video date" +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" msgstr "" -#: rapid/renamesubfolderprefs.py:201 -msgid "Today" +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " msgstr "" -#: rapid/renamesubfolderprefs.py:202 -msgid "Yesterday" +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " msgstr "" -#. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 -msgid "Download time" +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 -msgid "Name + extension" +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:208 -msgid "Name" +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 -msgid "Extension" +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 -msgid "Image number" +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " msgstr "" -#: rapid/renamesubfolderprefs.py:213 -msgid "Video number" +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 -msgid "Aperture" +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 -msgid "ISO" +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:219 -msgid "Exposure time" +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:221 -msgid "Focal length" +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:223 -msgid "Camera make" +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:225 -msgid "Camera model" +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:227 -msgid "Short camera model" +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:229 -msgid "Hyphenated short camera model" +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:231 -msgid "Serial number" +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:233 -msgid "Shutter count" +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:235 -msgid "Owner name" +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." msgstr "" -#: rapid/renamesubfolderprefs.py:236 -msgid "Codec" +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." msgstr "" -#: rapid/renamesubfolderprefs.py:237 -msgid "Width" +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." msgstr "" -#: rapid/renamesubfolderprefs.py:238 -msgid "Height" +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " msgstr "" -#: rapid/renamesubfolderprefs.py:239 -msgid "Length" +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." msgstr "" -#: rapid/renamesubfolderprefs.py:240 -msgid "Frames Per Second" +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 -msgid "Downloads today" +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:244 -msgid "Session number" +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:246 -msgid "Subfolder number" +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:248 -msgid "Stored number" +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:250 -msgid "Sequence letter" +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:252 -msgid "All digits" +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:254 -msgid "Last digit" +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:256 -msgid "Last 2 digits" +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:258 -msgid "Last 3 digits" +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:260 -msgid "Last 4 digits" +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" msgstr "" -#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:262 -msgid "Original Case" +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" msgstr "" -#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:264 -msgid "UPPERCASE" +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" msgstr "" -#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 -msgid "lowercase" +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" msgstr "" -#: rapid/renamesubfolderprefs.py:267 -msgid "One digit" +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "" -#: rapid/renamesubfolderprefs.py:268 -msgid "Two digits" +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" msgstr "" -#: rapid/renamesubfolderprefs.py:269 -msgid "Three digits" +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" msgstr "" -#: rapid/renamesubfolderprefs.py:270 -msgid "Four digits" +#: rapid/subfolderfile.py:339 +msgid "subfolder and filename" msgstr "" -#: rapid/renamesubfolderprefs.py:271 -msgid "Five digits" +#: rapid/subfolderfile.py:377 +msgid "Failed to create download subfolder" msgstr "" -#: rapid/renamesubfolderprefs.py:272 -msgid "Six digits" +#: rapid/subfolderfile.py:378 +#, python-format +msgid "Path: %s" msgstr "" -#: rapid/renamesubfolderprefs.py:273 -msgid "Seven digits" +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 -msgid "Subseconds" +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 -msgid "YYYYMMDD" +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 -msgid "YYYY-MM-DD" +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:281 -msgid "YYMMDD" +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 -msgid "YY-MM-DD" +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:285 -msgid "MMDDYYYY" +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 -msgid "MMDDYY" +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 -msgid "MMDD" +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 -msgid "DDMMYYYY" +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 -msgid "DDMMYY" +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 -msgid "YYYY" +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 -msgid "YY" +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 -msgid "MM" +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 -msgid "DD" +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 -msgid "HHMMSS" +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 -msgid "HHMM" +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 -msgid "HH-MM-SS" +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 -msgid "HH-MM" +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 -msgid "HH" +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 -msgid "MM (minutes)" +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" msgstr "" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 -msgid "SS" +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" msgstr "" -#: rapid/renamesubfolderprefs.py:800 -#, python-format -msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" msgstr "" -#: rapid/renamesubfolderprefs.py:807 -#, python-format -msgid "Preference value '%(value)s' is invalid" +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." msgstr "" -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" msgstr "" -#: rapid/renamesubfolderprefs.py:1524 -#, python-format -msgid "Subfolder preferences should not start with a %s" +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." msgstr "" -#: rapid/renamesubfolderprefs.py:1526 -#, python-format -msgid "Subfolder preferences should not end with a %s" +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" msgstr "" -#: rapid/renamesubfolderprefs.py:1530 -#, python-format -msgid "Subfolder preferences should not contain two %s one after the other" +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" msgstr "" -#: rapid/glade3/rapid.glade.h:1 +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr "" -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr "" - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr "" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr "" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 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 +#: rapid/glade3/prefs.ui.h:20 msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:23 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.h:27 msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.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:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." msgstr "" -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1632,152 +1527,107 @@ msgid "" "reader.</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" msgstr "" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" msgstr "" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 +msgid "Generate thumbnails (slower)" +msgstr "" + +#: rapid/glade3/prefs.ui.h:53 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:54 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." msgstr "" -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:55 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:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:56 msgid "Job Codes" msgstr "" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:57 msgid "Location:" msgstr "" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:58 +msgid "Miscillaneous" +msgstr "" + +#: rapid/glade3/prefs.ui.h:59 msgid "Overwrite" msgstr "" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" +#: rapid/glade3/prefs.ui.h:60 +msgid "Performance" msgstr "" -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo Folders" msgstr "" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:62 msgid "Photo Rename" msgstr "" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:63 msgid "Photo backup folder name:" msgstr "" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:64 msgid "Preferences: Rapid Photo Downloader" msgstr "" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:66 msgid "R_emove All" msgstr "" -#: rapid/glade3/rapid.glade.h:72 -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:77 +#: rapid/glade3/prefs.ui.h:67 msgid "Rename Options" msgstr "" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:68 msgid "Skip" msgstr "" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:69 msgid "Skip download" msgstr "" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:70 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " "python." msgstr "" -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:71 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1786,136 +1636,76 @@ msgid "" "a folder in it with one of these names.</i>" msgstr "" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:74 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:91 +#: rapid/glade3/prefs.ui.h:75 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." msgstr "" -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:76 msgid "Start downloading at program startup" msgstr "" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:77 msgid "Start downloading upon device insertion" msgstr "" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:78 msgid "Stored number:" msgstr "" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:79 msgid "Strip incompatible characters" msgstr "" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:80 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:81 msgid "Unmount (\"eject\") device upon download completion" msgstr "" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:82 msgid "Video Folders" msgstr "" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:83 msgid "Video Rename" msgstr "" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:84 msgid "Video backup folder name:" msgstr "" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:85 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." msgstr "" -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:86 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." msgstr "" -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:87 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." msgstr "" -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:88 msgid "_Add..." msgstr "" -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "" - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "" - -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "" - -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "" - -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "" - -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "" - -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "" - -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "" - -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "" - -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "" - -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" msgstr "" @@ -7,247 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" +"POT-Creation-Date: 2011-03-20 18:23-0500\n" "PO-Revision-Date: 2011-03-15 12:19+0000\n" "Last-Translator: bert <crinbert@yahoo.com>\n" "Language-Team: Romanian <ro@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: 2011-03-20 22:12+0000\n" -"X-Generator: Launchpad (build 12617)\n" +"X-Launchpad-Export-Date: 2011-04-04 05:24+0000\n" +"X-Generator: Launchpad (build 12710)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:97 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Foto Descărcător" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "New York" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "Manila" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "Praga" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "Helsinki" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "Wellington" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "Teheran" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "Kampala" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "Paris" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "Berlin" - -#: rapid/rapid.py:463 -msgid "Sydney" -msgstr "Sydney" - -#: rapid/rapid.py:464 -msgid "Budapest" -msgstr "Budapesta" - -#: rapid/rapid.py:464 -msgid "Rome" -msgstr "Roma" - -#: rapid/rapid.py:464 -msgid "Moscow" -msgstr "Moscova" - -#: rapid/rapid.py:464 -msgid "Delhi" -msgstr "Delhi" - -#: rapid/rapid.py:464 -msgid "Warsaw" -msgstr "Varșovia" - -#: rapid/rapid.py:465 -msgid "Jakarta" -msgstr "Jakarta" - -#: rapid/rapid.py:465 -msgid "Madrid" -msgstr "Madrid" - -#: rapid/rapid.py:465 -msgid "Stockholm" -msgstr "Stockholm" - -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" -msgstr "Valoare Invalidă Descărcări Astăzi.\n" - -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" -msgstr "Se resetează valore la zero.\n" - -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "Valorile preferinței 'Pornirea zilei' sunt corupte.\n" - -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" -msgstr "Resetarea la miezul nopţii\n" - -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" -msgstr "Eroare în preferințele redenumirii fotografiei" - -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Aceste preferințe conțin o eroare:\n" - -#: rapid/rapid.py:609 -msgid "Resetting to default values." -msgstr "Se resetează la valori implicite." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" -msgstr "Cod sarcină" - -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" -msgstr "Eroare în preferințele redenumirii fișierului video" - -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" -msgstr "Eroare în preferințe Subdosar Descărcări Foto" - -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" -msgstr "Eroare în preferințe Subdosar Descărcări Video" - -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" -msgstr "fotografii și video" - -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 -msgid "photos" -msgstr "fotografii" - -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "Alegeți un dosar unde să fie descărcate fotografiile" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" -msgstr "Selectează un dosar unde descarc video" - -#: rapid/rapid.py:1055 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Selectaţi un dosar ce conţine %(file_types)s" - -#: rapid/rapid.py:1077 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "Selectați un dosar unde faceți o copie de siguranță a %(file_types)s" - -#. 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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" -"<i><b>Avertivare:</b> Nu există suficiente metadate pentru a genera pe " -"deplin numele. Folosiţi alte opţiuni de redenumire.</i>" - -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" -msgstr "" -"<i><b>Avertizare:</b> Insuficiente metadata pentru generare complectă a " -"subdosarului. Folosiți opțiunea de denumire.</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:1198 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Exemple: %s<i/>" - -#: rapid/rapid.py:1224 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"Valoare descărcări de astăzi nu a fost actualizată, pentru că o descărcare " -"are loc în prezent" - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Valoare număr stocare nu a fost actualizat, pentru că o descărcare are loc " -"în prezent" - -#: rapid/rapid.py:1270 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "" -"Preferințele subdosarului %(filetype)s au fost șterse câteva valori inutile." - -#. Preferences list is now empty -#: rapid/rapid.py:1275 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" -"Preferințele %(filetype)s subdosarului introduse sunt invalide și nu pot fi " -"folosite.\n" -"Ele vor fi resetate la valori implicte." - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" -msgstr "fotografie" - -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" -msgstr "video" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -msgid "externaldrive1" -msgstr "dispozitiv extern 1" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1529 -msgid "externaldrive2" -msgstr "dispozitiv extern 2" - -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" -msgstr "fotografii și video" - -#: rapid/rapid.py:1556 -msgid "videos" -msgstr "video" - -#: rapid/rapid.py:1568 +#: rapid/rapid.py:102 #, python-format msgid "" "%(date)s\n" @@ -256,827 +31,127 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1570 +#: rapid/rapid.py:104 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1573 +#: rapid/rapid.py:107 #, python-format msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1580 +#: rapid/rapid.py:114 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" -msgstr "subdosare si nume fișiere" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:145 +msgid "Device" +msgstr "Dispozitiv" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" -msgstr "nume fișier" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:159 +msgid "Size" +msgstr "Mărime" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" -msgstr "subdosar" +#: rapid/rapid.py:162 +msgid "Download Progress" +msgstr "Progresul Descărcării" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 +#: rapid/rapid.py:938 msgid "scanning..." msgstr "scanez" -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" -msgstr "Următoarea cale de descărcare nu a putut fi creată:\n" - -#: rapid/rapid.py:1819 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 -msgid "Download cannot proceed" -msgstr "Descărcarea nu poate continua" - -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." -msgstr "Este o eroare în preferințe program." - -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." +#: rapid/rapid.py:1639 +msgid "Download" msgstr "" -"\n" -"Verificați preferințele, reporniți, și încercați din nou." -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2019 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#: rapid/rapid.py:1642 +msgid "Pause" msgstr "" -"Scanare dispozitiv complectă: găsite %(number)s %(filetypes)s în %(device)s" - -#: rapid/rapid.py:2026 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "Scanare dispozitiv complectă: nu sunt %(filetypes)s în %(device)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:2047 -msgid "The device can now be safely removed" -msgstr "Dispozitivul poate fi scos în siguranță" - -#: rapid/rapid.py:2053 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s descărcate" - -#: rapid/rapid.py:2056 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "%(noFiles)s %(filetypes)s descărcare eșuată" - -#: rapid/rapid.py:2059 rapid/rapid.py:5901 -msgid "warnings" -msgstr "avertismente" - -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" -msgstr "erori" - -#: rapid/rapid.py:2091 -#, python-format -msgid "Source: %s\n" -msgstr "Sursă: %s\n" - -#: rapid/rapid.py:2093 -#, python-format -msgid "Device: %s\n" -msgstr "Dispozitiv: %s\n" -#: rapid/rapid.py:2094 -#, python-format -msgid "Destination: %s" -msgstr "Destinație: %s" - -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" -msgstr "Nu am putut crea directorul temporar de descărcare" - -#: rapid/rapid.py:2098 -msgid "Error:" -msgstr "Eroare:" - -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" -msgstr "Calea copiei de siguranță nu există" - -#: rapid/rapid.py:2123 -#, python-format -msgid "The path %s could not be created" -msgstr "Calea %s nu poate fi creată" - -#: rapid/rapid.py:2124 -msgid "No backups can occur" -msgstr "Copii de siguranță nu pot avea loc" - -#: rapid/rapid.py:2153 -#, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" -msgstr "" -"Sursă: %(source)s\n" -"Detinație: %(destination)s\n" -"%(problem)s" - -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 -#, python-format -msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" -msgstr "" -"Sursă: %(source)s\n" -"Destinație: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "Verificați-vă sistemul și încercați din nou." - -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" -"Fotografii detectate cu același nume de fișier, dar făcute în timpi diferiți" - -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" -msgstr "Fotografia este deja descărcată" - -#: rapid/rapid.py:2260 rapid/rapid.py:2659 -#, python-format -msgid "Source: %(source)s" -msgstr "Sursă: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "" -"Nouă zi a început - resetați numărul de secvență \"Descărcările de azi\"" - -#: rapid/rapid.py:2529 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Copia de siguranță a %(file_type)s există deja" - -#: rapid/rapid.py:2533 -#, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "Copia de siguranță %(file_type)s va fi rescrisă" - -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "%(file_type)s nu s-a copiat de siguranță în %(volume)s" - -#: rapid/rapid.py:2539 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "%(file_type)s nu s-a copiat de siguranță" - -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" -msgstr "Eroare copiere de siguranță" - -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Directorul de destinație nu poate fi creat: %(directory)s\n" - -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" -msgstr "Erori: %(inst)s" - -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "Acest %(file_type)s nu s-a creat în copia de siguranță." - -#: rapid/rapid.py:2595 rapid/rapid.py:2645 -#, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Eroare: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2658 -#, python-format -msgid "%(file_type)s could not be backed up" -msgstr "%(file_type)s nu pot fi copiate în siguranță" - -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" -msgstr "N-am găsit nici un volum de rezervă adecvat" - -#: rapid/rapid.py:2663 -msgid "A backup location was not found" -msgstr "Locația copiei de rezervă nu a fost găsită" - -#: rapid/rapid.py:2717 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." -msgstr "" -"Acest dispozitiv nu are %(types_searched_for)s pentru a fi descărcate." - -#: rapid/rapid.py:2813 -#, python-format -msgid "Download has started from %s" -msgstr "Descărcarea a început de la %s" - -#: rapid/rapid.py:2817 -#, python-format -msgid "Attempting to download %s files" -msgstr "Aștept să descarc %s fișiere" - -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 +#. ~ scan_pid = rpd_file.scan_pid +#. ~ unique_id = rpd_file.unique_id +#: rapid/rapid.py:1906 #, python-format msgid "%(number)s of %(total)s %(filetypes)s" msgstr "%(number)s din %(total)s %(filetypes)s" -#: rapid/rapid.py:2913 -#, python-format -msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" -msgstr "%(number)s din %(total)s %(filetypes)s (%(remaining)s remaining)" +#: rapid/rapid.py:2239 rapid/preferencesdialog.py:817 rapid/rpdfile.py:118 +msgid "photos" +msgstr "fotografii" -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" -msgstr "Nu pot șterge fotografii sau video din dispozitiv" +#: rapid/rapid.py:2241 rapid/rpdfile.py:113 +msgid "videos" +msgstr "video" -#: rapid/rapid.py:2939 -#, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" +#: rapid/rapid.py:2244 +msgid "Free space:" msgstr "" -"Fotografie: %(source)s\n" -"Eroare: %(errno)s %(strerror)s" - -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" -msgstr "Fotografie: %(source)s" - -#: rapid/rapid.py:2945 -#, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "Șterse %(number)i %(filetypes)s din dispozitiv" -#: rapid/rapid.py:2958 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2256 #, python-format -msgid "Download complete from %s" -msgstr "Descărcare complectă din %s" - -#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc. -#: rapid/rapid.py:3073 rapid/rapid.py:3542 -msgid "Device" -msgstr "Dispozitiv" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" -msgstr "Mărime" - -#: rapid/rapid.py:3081 -msgid "Download Progress" -msgstr "Progresul Descărcării" - -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" -msgstr "Descărcarea din Aparat" - -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" -msgstr "Descărcarea direct din aparat s-ar putea să lucreze slab sau deloc" - -#: rapid/rapid.py:3176 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." -msgstr "" -"Descărcarea de la un cititor de card funcţionează întotdeauna şi este, în " -"general, mult mai rapid. Este recomandat să utilizaţi un cititor de card." - -#: rapid/rapid.py:3190 -msgid "_Show this message again" -msgstr "_Arată acest mesaj din nou" - -#: rapid/rapid.py:3225 -msgid "Device Detected" -msgstr "Dispozitiv Detectat" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "" -"Should this device or partition be used to download photos or videos from?" +msgid "(%(file_type)s)" msgstr "" -"Poate acest dispozitiv sau partiție să fie folosit pentru descărcare " -"fotografii sau video de la?" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 -msgid "_Remember this choice" -msgstr "_Amintiţi-vă această alegere" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2260 #, python-format -msgid "%s selected for downloading from" -msgstr "%s selectate pentru descărcare de la" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" +msgid "%(free)s %(file_type)s" msgstr "" -"Acest dispozitiv sau partiţie va fi întotdeauna folosit pentru a descărca de " -"la" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s rejectat ca și dispozitiv de descărcare" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2265 +msgid "; " msgstr "" -"Acest dispozitiv sau partiţie nu va fi folosit pentru a descărca de la" - -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" -msgstr "Eliminați toate Codurile Sarcină" - -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" -msgstr "Să elimin toate Codurile Sarcină" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" -msgstr "Introduceți un Cod Sarcină" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" -msgstr "Introduceți un nou Cod Sarcină, sau selectați unul precedent" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" -msgstr "Introduceți un nou Cod Sarcină" - -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" -msgstr "Cod Sarcină" - -#: rapid/rapid.py:3425 -msgid "Job Code entered" -msgstr "Cod Sarcină introdus" -#: rapid/rapid.py:3427 -msgid "Job Code not entered" -msgstr "Codul Sarcină nu s-a introdus" - -#: rapid/rapid.py:3477 -msgid "Status" -msgstr "Status" - -#: rapid/rapid.py:3485 -msgid "Type" -msgstr "Tip" - -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" -msgstr "Fotografie" - -#: rapid/rapid.py:3496 -msgid "File" -msgstr "Fișier" - -#: rapid/rapid.py:3511 -msgid "Job Code" -msgstr "Cod Sarcină" - -#: rapid/rapid.py:3521 -msgid "Date" -msgstr "Dată" - -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" -msgstr "Nume fișier" - -#: rapid/rapid.py:3564 -msgid "Path" -msgstr "Cale" - -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s a fost descărcate cu succes" - -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s nu au fost descărcate" - -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s au fost descărcate cu avertizări" - -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2270 +msgid "." msgstr "" -"%(filetype)s au fost descărcate dar sunt probleme pentru copieri de siguranță" - -#: rapid/rapid.py:3982 -#, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "%(filetype)s nu trebuie descărcate sau copiate de siguranță" - -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s sunt deja descărcate" - -#: rapid/rapid.py:3986 -#, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "%(filetype)s vor fi descărcate" -#: rapid/rapid.py:3988 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2276 #, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s vor fi descărcate cu avertizări" - -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s nu pot fi descărcate" - -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "Introduceți un nou Cod Sarcină, sau selectați unul existent" - -#: rapid/rapid.py:5034 -#, python-format -msgid "%(free)s available" -msgstr "%(free)s disponibile" +msgid "%(free)s free" +msgstr "" #. user manually specified backup location -#: rapid/rapid.py:5040 +#: rapid/rapid.py:2282 #, python-format msgid "Backing up to %(path)s" msgstr "Copiez de siguranță în %(path)s" -#: rapid/rapid.py:5045 +#: rapid/rapid.py:2287 #, python-format msgid "%(freespace)s. %(backuppaths)s." msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" -"Locația dispozitivului nu există:\n" -"%(path)s\n" -"Rezolvaţi problema, sau modificați preferinţele dvs." - -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" -msgstr "Problemă cu Locația Dosarului Dispozitivului" - -#: rapid/rapid.py:5067 -msgid "Video" -msgstr "Video" - -#: rapid/rapid.py:5074 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "Dosarul %(file_type)s de Descărcări nu există.\n" - -#: rapid/rapid.py:5083 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "Dosarul %(file_type)s de Descărcări există dar nu poate fi scris.\n" - -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" -"Probleme au fost întâmpinate cu dosarele de descărcare. Corectaţi problemele " -"sau să modificați preferinţele.\n" -"\n" - -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" -msgstr "Probleme cu Dosarul de Descărcare" - -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" -msgstr "Probleme cu Dosarele de Descărcare" - -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." -msgstr "Câteva preferințe vor fi resetate." - -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" -msgstr "Afişarea avertisment despre descărcarea direct de la aparat" - -#: rapid/rapid.py:5149 -#, python-format -msgid "Prompting whether to use %s" -msgstr "Determinați dacă doriţi să utilizaţi %s" - -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" -msgstr "Determinați pentru Cod Sarcină" - -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Deja determinat pentru Cod Sarcină, nu solicita din nou" - -#: rapid/rapid.py:5197 -msgid "Starting downloads" -msgstr "Pornire descărcări" - -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "Ponesc descărcarea care așteaptă un Cod Sarcină" - -#: rapid/rapid.py:5248 -#, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "Crearea Dosarului de descărcare fotografii %(folder)s" - -#: rapid/rapid.py:5253 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "Nu am reușit să creez dosar descărcare fotografii %(folder)s" - -#: rapid/rapid.py:5257 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "Crearea dosarului de descărcări video %(folder)s" - -#: rapid/rapid.py:5262 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "Nu am reușit să creez dosar descărcare video %(folder)s" - -#: rapid/rapid.py:5287 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" -msgstr "" -"O versiune mai nouă a acestui program a fost anterior executa pe acest " -"computer.\n" -"\n" - -#: rapid/rapid.py:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"Preferinţele programului par a fi valabil, verificaţi pentru a asigura " -"funcţionarea corectă." - -#: rapid/rapid.py:5291 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "Unele preferinţe sunt invalide şi vor fi resetate." - -#: rapid/rapid.py:5292 -msgid "Warning:" -msgstr "Atenție:" - -#: rapid/rapid.py:5297 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." -msgstr "" -"Această versiune a programului este mai nouă decât versiunea anterioară ce " -"rulează. Verificați preferinţele." - -#: rapid/rapid.py:5304 -msgid "Preferences were modified." -msgstr "Preferințele au fost modificate" - -#: rapid/rapid.py:5305 -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 "" -"Această versiune de program folosește preferințe diferite decât versiunea " -"veche. Preferințele dvs. au fost actualizate.\n" -"\n" -"Verificaţi-le pentru a asigura funcţionarea corectă." - -#: rapid/rapid.py:5309 -msgid "No preferences needed to be changed." -msgstr "Nicio preferință nu trebuie modificată." - -#: rapid/rapid.py:5311 -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 "" -"Această versiune de program folosește preferințe diferite decât versiunea " -"veche. Câteva din preferințe sunt invalide și nu pot fi actualizate. Ele vor " -"fi resetate." - -#: rapid/rapid.py:5321 -msgid "Problem using pynotify." -msgstr "Probleme folosind notificarea py." - -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." -msgstr "" - -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Avertizare: mediul desktop este configurat incorect pentru notificare server." - -#: rapid/rapid.py:5396 -msgid "and" -msgstr "și" - -#: rapid/rapid.py:5401 -msgid "Using backup devices" -msgstr "Folosesc copia de siguranță a dispozitivelor" - -#: rapid/rapid.py:5403 -msgid "Using backup device" -msgstr "Folosesc copia de siguranță a dispozitivului" - -#: rapid/rapid.py:5405 -msgid "No backup devices detected" -msgstr "Nu am găsit copie de siguranță a dispozitivului" - -#: rapid/rapid.py:5455 rapid/rapid.py:5617 -#, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Dispozitiv %(device)s (%(path)s) ignorat" - -#: rapid/rapid.py:5576 -#, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Detectat %(device)s cu calea %(path)s" - -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" -msgstr "Pornirea descărcării în mod automat este adevărată" - -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" -msgstr "Pornirea descărcării în mod automat este falsă" - -#: rapid/rapid.py:5635 -msgid "Using manually specified path" -msgstr "Utilizând o cale specificată manual" - -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 -#, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" +#: rapid/rapid.py:2470 +msgid "Thumbnails" msgstr "" -"Atenție: copia de siguranță a dispozitivului %(device)s este în curs de " -"descărcare de pe" - -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" -msgstr "D_escărcări Selectate" - -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" -msgstr "Toate descărcările complecte" - -#: rapid/rapid.py:5837 -msgid "MB/s" -msgstr "MB/s" - -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" -msgstr "Aproximativ 1 secundă rămâne" - -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" -msgstr "Aproximativ %i secunde rămân" - -#: rapid/rapid.py:5851 -msgid "About 1 minute remaining" -msgstr "Aprozimativ 1 minut rămâne" - -#. 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:5856 -#, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Aproximativ %(minutes)i:%(seconds)-2i minute rămân" - -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" - -#: rapid/rapid.py:5878 rapid/rapid.py:5890 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s descărcate" - -#: rapid/rapid.py:5884 rapid/rapid.py:5896 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "%(filetype)s au eşuat la descărcare" - -#: rapid/rapid.py:6070 -msgid "_Resume" -msgstr "_Reluare" - -#: rapid/rapid.py:6073 -msgid "_Download All" -msgstr "_Descarcă Tot" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" -msgstr "_Pauză" - -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." -msgstr "Setări preferințe descărcare din dispozitiv au fost schimbate." - -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." -msgstr "Preferințele copiei de siguranță au fost schimbate." - -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." -msgstr "Preferințele subdosarului și numelui fișier au fost schimbate." - -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." -msgstr "Descarcă preferințele dosarului după modificare." - -#: rapid/rapid.py:6422 -msgid "Goodbye" -msgstr "La revedere" #. 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:6433 +#: rapid/rapid.py:2511 #, python-format msgid "" "display program information on the command line as the program runs " @@ -1085,585 +160,1176 @@ msgstr "" "afișare informații program în linia de comandă când programul rulează " "(default: %default)" -#: rapid/rapid.py:6434 +#: rapid/rapid.py:2512 msgid "display debugging information when run from the command line" msgstr "afișare informații depanare în linia de coandă atunci când rulează" -#: rapid/rapid.py:6435 +#: rapid/rapid.py:2513 msgid "only output errors to the command line" msgstr "doar erorile de ieșire în linie de comandă" #. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6437 +#: rapid/rapid.py:2515 msgid "list photo and video file extensions the program recognizes and exit" msgstr "" "listează extensiile fișierului fotografie și video pe care progamul le " "recunoaște și ieși" -#: rapid/rapid.py:6438 +#: rapid/rapid.py:2516 msgid "reset all program settings and preferences and exit" msgstr "resetează toate setările și preferințele și ieși" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:2529 msgid "Photos:" msgstr "Fotografii:" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:2529 msgid "Videos:" msgstr "Video-uri" -#: rapid/rapid.py:6457 +#: rapid/rapid.py:2534 #, python-format msgid "and %s" msgstr "și %s" -#: rapid/rapid.py:6465 +#: rapid/rapid.py:2542 msgid "All settings and preferences have been reset" msgstr "Toate setările și preferințele au fost resetate" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" -msgstr "utilizând" +#: rapid/rapid.py:2551 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." +msgstr "" -#: rapid/rapid.py:6474 -msgid "\n" -msgstr "\n" +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Dispozitiv Detectat" -#. this application is already running -#: rapid/rapid.py:6498 -#, python-format -msgid "%s is already running" -msgstr "%s este deja în execuţie" +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "" +"Poate acest dispozitiv sau partiție să fie folosit pentru descărcare " +"fotografii sau video de la?" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "_Amintiţi-vă această alegere" -#: rapid/renamesubfolderprefs.py:192 +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Dată timp" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Text" -#: rapid/renamesubfolderprefs.py:195 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Nume fișier" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Metadata" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Secvenţe" -#: rapid/renamesubfolderprefs.py:199 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:545 +msgid "Job code" +msgstr "Cod sarcină" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Dată imagine" -#: rapid/renamesubfolderprefs.py:200 +#: rapid/generatenameconfig.py:151 msgid "Video date" msgstr "Dată video" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Astăzi" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Ieri" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 +#: rapid/generatenameconfig.py:155 msgid "Download time" msgstr "Timp descărcare" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 +#: rapid/generatenameconfig.py:157 msgid "Name + extension" msgstr "Nume + extensie" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:208 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Nume" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 +#: rapid/generatenameconfig.py:161 msgid "Extension" msgstr "Extensie" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Număr imagine" -#: rapid/renamesubfolderprefs.py:213 +#: rapid/generatenameconfig.py:164 msgid "Video number" msgstr "Număr video" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Diafragmă" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 +#: rapid/generatenameconfig.py:168 msgid "ISO" msgstr "ISO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:219 +#: rapid/generatenameconfig.py:170 msgid "Exposure time" msgstr "Timp expunere" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:221 +#: rapid/generatenameconfig.py:172 msgid "Focal length" msgstr "Distanță focală" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:223 +#: rapid/generatenameconfig.py:174 msgid "Camera make" msgstr "Fabricant cameră foto" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:225 +#: rapid/generatenameconfig.py:176 msgid "Camera model" msgstr "Model cameră foto" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:227 +#: rapid/generatenameconfig.py:178 msgid "Short camera model" msgstr "Model scurt cameră foto" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:229 +#: rapid/generatenameconfig.py:180 msgid "Hyphenated short camera model" msgstr "Silabisire scurtă model cameră foto" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:231 +#: rapid/generatenameconfig.py:182 msgid "Serial number" msgstr "Număr serie" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:233 +#: rapid/generatenameconfig.py:184 msgid "Shutter count" msgstr "Calcul obturator" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:235 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Nume proprietar" -#: rapid/renamesubfolderprefs.py:236 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Codec" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Lățime" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Înălțime" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Lungime" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Cadre pe secundă" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 +#: rapid/generatenameconfig.py:193 msgid "Downloads today" msgstr "Descărcările de azi" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:244 +#: rapid/generatenameconfig.py:195 msgid "Session number" msgstr "Numărul sesiunii" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:246 +#: rapid/generatenameconfig.py:197 msgid "Subfolder number" msgstr "Număr subdosare" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:248 +#: rapid/generatenameconfig.py:199 msgid "Stored number" msgstr "Număr stocare" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:250 +#: rapid/generatenameconfig.py:201 msgid "Sequence letter" msgstr "Secvență literă" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:252 +#: rapid/generatenameconfig.py:203 msgid "All digits" msgstr "Toți digiți" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:254 +#: rapid/generatenameconfig.py:205 msgid "Last digit" msgstr "Ultimul digit" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:256 +#: rapid/generatenameconfig.py:207 msgid "Last 2 digits" msgstr "Ultimii 2 digiți" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:258 +#: rapid/generatenameconfig.py:209 msgid "Last 3 digits" msgstr "Ultimii 3 digiți" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:260 +#: rapid/generatenameconfig.py:211 msgid "Last 4 digits" msgstr "Ultimii 4 digiți" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:262 +#: rapid/generatenameconfig.py:213 msgid "Original Case" msgstr "Format original" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:264 +#: rapid/generatenameconfig.py:215 msgid "UPPERCASE" msgstr "MAJUSCULE" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "minuscule" -#: rapid/renamesubfolderprefs.py:267 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Un digit" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Doi digiți" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Trei digiți" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Patru digiți" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Cinci digiți" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Șase digiți" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "Șapte digiți" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 +#: rapid/generatenameconfig.py:226 msgid "Subseconds" msgstr "Milisecunde" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "AAAALLZZ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 +#: rapid/generatenameconfig.py:230 msgid "YYYY-MM-DD" msgstr "AAAA-LL-ZZ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:281 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "AALLZZ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 +#: rapid/generatenameconfig.py:234 msgid "YY-MM-DD" msgstr "AA-LL-ZZ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:285 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "LLZZAAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "LLZZAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "LLZZ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "ZZLLAAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "ZZLLAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "AAAA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "AA" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "LL" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "ZZ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "OOMMSS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "OOMM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "OO-MM-SS" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "OO-MM" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "OO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "MM (minute)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "SS" -#: rapid/renamesubfolderprefs.py:800 +#: rapid/preferencesdialog.py:364 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Preferințele subdosarului nu se poate începe cu %s" + +#: rapid/preferencesdialog.py:366 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Preferințele subdosarului nu se pot termina cu %s" + +#: rapid/preferencesdialog.py:370 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "" +"Preferințele subdosarului nu trebuie să conțină două %s una după alta" + +#: rapid/preferencesdialog.py:384 rapid/preferencesdialog.py:668 +msgid "Remove all Job Codes?" +msgstr "Eliminați toate Codurile Sarcină" + +#: rapid/preferencesdialog.py:401 rapid/preferencesdialog.py:685 +msgid "Should all Job Codes be removed?" +msgstr "Să elimin toate Codurile Sarcină" + +#: rapid/preferencesdialog.py:431 +msgid "Error in Photo Rename preferences" +msgstr "Eroare în preferințele redenumirii fotografiei" + +#: rapid/preferencesdialog.py:613 +msgid "Error in Video Rename preferences" +msgstr "Eroare în preferințele redenumirii fișierului video" + +#: rapid/preferencesdialog.py:634 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Eroare în preferințe Subdosar Descărcări Foto" + +#: rapid/preferencesdialog.py:651 +msgid "Error in Video Download Subfolders preferences" +msgstr "Eroare în preferințe Subdosar Descărcări Video" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:710 +msgid "Enter a Job Code" +msgstr "Introduceți un Cod Sarcină" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:727 +msgid "Enter a new Job Code, or select a previous one" +msgstr "Introduceți un nou Cod Sarcină, sau selectați unul precedent" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:730 +msgid "Enter a new Job Code" +msgstr "Introduceți un nou Cod Sarcină" + +#: rapid/preferencesdialog.py:735 +msgid "Job Code:" +msgstr "Cod Sarcină" + +#: rapid/preferencesdialog.py:815 rapid/rpdfile.py:108 +msgid "photos and videos" +msgstr "fotografii și video" + +#: rapid/preferencesdialog.py:964 +msgid "Select a folder to download photos to" +msgstr "Alegeți un dosar unde să fie descărcate fotografiile" + +#: rapid/preferencesdialog.py:982 +msgid "Select a folder to download videos to" +msgstr "Selectează un dosar unde descarc video" + +#: rapid/preferencesdialog.py:1064 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Selectaţi un dosar ce conţine %(file_types)s" + +#: rapid/preferencesdialog.py:1086 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "Selectați un dosar unde faceți o copie de siguranță a %(file_types)s" + +#. 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/preferencesdialog.py:1172 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Avertivare:</b> Nu există suficiente metadate pentru a genera pe " +"deplin numele. Folosiţi alte opţiuni de redenumire.</i>" + +#: rapid/preferencesdialog.py:1211 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Avertizare:</b> Insuficiente metadata pentru generare complectă a " +"subdosarului. Folosiți opțiunea de denumire.</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/preferencesdialog.py:1215 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Exemple: %s<i/>" + +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1291 +#, python-format +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." +msgstr "" +"Preferințele %(filetype)s subdosarului introduse sunt invalide și nu pot fi " +"folosite.\n" +"Ele vor fi resetate la valori implicte." + +#. check subfolder preferences for bad values +#: rapid/preferencesdialog.py:1305 rapid/rpdfile.py:120 rapid/rpdfile.py:241 +msgid "photo" +msgstr "fotografie" + +#: rapid/preferencesdialog.py:1306 rapid/rpdfile.py:115 rapid/rpdfile.py:267 +msgid "video" +msgstr "video" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1566 +msgid "externaldrive1" +msgstr "dispozitiv extern 1" + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1568 +msgid "externaldrive2" +msgstr "dispozitiv extern 2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "New York" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Manila" + +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Praga" + +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Helsinki" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Wellington" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Teheran" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Kampala" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Paris" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Berlin" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Sydney" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Budapesta" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Roma" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Moscova" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Delhi" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Varșovia" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Jakarta" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Madrid" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Stockholm" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:181 +msgid "subfolder" +msgstr "subdosar" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:179 +msgid "filename" +msgstr "nume fișier" + +#: rapid/problemnotification.py:80 +#, python-format +msgid "Date time value %s appears invalid." +msgstr "" + +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "" + +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "" + +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." +msgstr "" + +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" +msgstr "" + +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" +msgstr "" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "" + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "" + +#: rapid/problemnotification.py:97 +#, python-format +msgid "" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." +msgstr "" + +#: rapid/problemnotification.py:102 #, python-format msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." msgstr "" -"Preferința cheii '%(key)s' este invalidă\n" -"Aștept una dintre %(value)s" -#: rapid/renamesubfolderprefs.py:807 +#: rapid/problemnotification.py:103 #, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "Valoare preferință %(value)s' este invalidă" +msgid "%(filetype)s was already downloaded" +msgstr "" -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" -msgstr "Aceste preferinţe nu sunt bine formate:" +#: rapid/problemnotification.py:107 +#, python-format +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." +msgstr "" -#: rapid/renamesubfolderprefs.py:1524 +#: rapid/problemnotification.py:108 #, python-format -msgid "Subfolder preferences should not start with a %s" -msgstr "Preferințele subdosarului nu se poate începe cu %s" +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "" -#: rapid/renamesubfolderprefs.py:1526 +#: rapid/problemnotification.py:109 #, python-format -msgid "Subfolder preferences should not end with a %s" -msgstr "Preferințele subdosarului nu se pot termina cu %s" +msgid "There is no data with which to name the %(filetype)s." +msgstr "" -#: rapid/renamesubfolderprefs.py:1530 +#: rapid/problemnotification.py:111 #, python-format -msgid "Subfolder preferences should not contain two %s one after the other" +msgid "Error: %(errorno)s %(strerror)s" +msgstr "" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "" + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "" + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr "" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr "" + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "" + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "" + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "" + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "" + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "" + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "" + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "" + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "" + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "" + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "" + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "" + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "" + +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr "" + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr "" + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "" + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "" + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "" + +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "" + +#: rapid/problemnotification.py:403 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "" +"Fotografii detectate cu același nume de fișier, dar făcute în timpi diferiți" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "" + +#: rapid/rpdfile.py:110 +msgid "photos or videos" +msgstr "fotografii și video" + +#: rapid/rpdfile.py:134 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/rpdfile.py:242 +msgid "Photo" +msgstr "Fotografie" + +#: rapid/rpdfile.py:268 +msgid "Video" +msgstr "Video" + +#: rapid/subfolderfile.py:177 +msgid "subfolder and filename" +msgstr "subdosare si nume fișiere" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Descărcare / Pauză" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "Selectați tot c_u Cod Sarcină" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "Selectați tot fără _Cod Sarcină" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Curăță descărcările Complected" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" msgstr "" -"Preferințele subdosarului nu trebuie să conțină două %s una după alta" -#: rapid/glade3/rapid.glade.h:1 +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "_Erori Jurnal" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Fişier" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "_Ajutor" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Faceți o Donație..." + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Selectați" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Tradu această aplicație..." + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "_Vizualizează" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " oo:mm" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "Copie de rezervă" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Compatibilitate cu Alt Sistem de Operare</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "<b>Dispozitiv</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Dosar Descărcare</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Subdosar Descărcări</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Exemplu</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Cod Sarcină</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "<b>Redenumire Fotografie</b>" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "<b>Conflicte în Nume Fotografii și Video</b>" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Program Automatizare</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Număr Secvență</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/media/dispozitiv extern/Fotografii</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Exemplu: /acasă/utilizator/Poze</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Exemplu:</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Nou:</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 msgid "<i>Original:</i>" msgstr "<i>Original:</i>" -#: rapid/glade3/rapid.glade.h:21 -msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" -msgstr "" -"Copy text \t\r\n" -"<span weight=\"bold\" size=\"x-large\">Automatizare</span>" - -#: rapid/glade3/rapid.glade.h:22 +#: rapid/glade3/prefs.ui.h:20 msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Copie de Rezervă</span>\t" -#: rapid/glade3/rapid.glade.h:23 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "" "Copy text \t\r\n" "<span weight=\"bold\" size=\"x-large\">Dispozitiv</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Eroare de manipulare</span>" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Coduri Sarcină</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Dosar Descărcări Fotografii</span>" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "" "<span weight=\"bold\" size=\"x-large\">Redenumire Fotografii</span>\t" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.h:27 msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Redenumire Opțiuni</span>" -#: rapid/glade3/rapid.glade.h:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Dosar Descărcări Video</span>" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Redenumire Video</span>\t" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Adaugă identificator unic" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Detectare automată a Dispozitivelor de Stocare Portabile" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Detectare automată a copiilor de siguranță a dispozitivelor" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Detectare automată dispozitive" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Automatizare" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Copie de rezervă" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Locație copie de rezervă" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "Copiază de siguranță fotografiile șî video cănd descărci" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1671,7 +1337,7 @@ msgstr "" "Alegeți dosarul de descărcări. Subdosarul pentru fotografiile descărcate va " "fi creat automat în acest dosar folosind structura de mai jos." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." @@ -1679,24 +1345,20 @@ msgstr "" "Alegeți dosarul de descărcări. Subdosarul pentru video descărcate va fi " "creat automat în acest dosar folosind structura de mai jos." -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Copyright Damon Lynch 2007-10" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Ziua de început:" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "" "Șterge fotografii și video din dispozitiv dacă descărcarea este complectă" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Dispozitive" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1718,38 +1380,33 @@ msgstr "" "sau deloc, încercaţi să-l setați pe modul PTP. În cazul în care nu este " "posibil, luaţi în considerare utilizarea unui cititor de card.</i>" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Descărcare / Pauză" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Dosarul de descărcare:" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Descărcări de azi:" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Tratarea erorilor" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Jurnal Erori" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" +msgstr "" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" msgstr "" -"Ieși din program dacă descărcarea este complectă fără atenționări și erori" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" "Dacă dezactivaţi detectarea automată, alegeţi locaţia copiei de rezervă " "exact." -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." @@ -1757,7 +1414,7 @@ msgstr "" "Dacă dezactivați detectarea automată, alegeți exact locația pentru " "fotografii și video-uri" -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1767,118 +1424,55 @@ msgstr "" "întregul dispozitiv va fi scanat pentru imagini. În cazul dispozitivelor " "mari, aceasta ar putea dura ceva timp." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "Importați fotografii și video eficien și fiabil" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Coduri Sarcină" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Locație:" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Suprascrie" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "P_revizualizare Coloane" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "Dosar Fotografii" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "Redenumire Fotografie" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "Numele dosarului copie de siguranță pentru fotografii:" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Preferințe: Rapid Foto Descărcător" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "Previzualizare _Dosare" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "Șt_erge tot" -#: rapid/glade3/rapid.glade.h:72 -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 este software liber, îl puteţi redistribui şi / sau " -"modifica sub termenii GNU General Public License publicate de Free Software " -"Foundation; fie versiunea 2 a Licenţei, sau (la opţiunea dumneavoastră) " -"orice versiune ulterioară.\n" -"\n" -"Rapid Photo Downloader este distribuit în speranţa că va fi folositor, dar " -"FĂRĂ NICI O GARANŢIE, nici chiar garanţia implicită de VANDABILITATE sau " -"POTRIVIRE PENTRU UN SCOP ANUME. Vezi GNU General Public License pentru mai " -"multe detalii.\n" -"\n" -"Trebuie să fi primit o copie a GNU General Public License, împreună cu Rapid " -"Photo Downloader, dacă nu, scrieţi la Free Software Foundation, Inc, 51 " -"Franklin Street, Fifth Floor, Boston, MA 02110 la 1301, Statele Unite ale " -"Americii." - -#: rapid/glade3/rapid.glade.h:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Opțiuni Redenumire" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "Se_lectat Nimic" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Selectați toate Fo_tografiile" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Selectați toate Vi_deo" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "Selectați tot c_u Cod Sarcină" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "Selectați tot fără _Cod Sarcină" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "Selectează _tot" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Omite" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Omite descărcare" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " @@ -1888,7 +1482,7 @@ msgstr "" "clipuri video, instalaţi <i>hachnoir metadata</i> și <i>kaa metadata</i> " "pachete pentru python." -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1904,7 +1498,7 @@ msgstr "" "dispozitiv pentru care faceți copie de siguranță, creați un dosar în el cu " "numele lui.</i>" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1912,7 +1506,7 @@ msgstr "" "Specificaţi ora în formatul de 24 de ore la care <i>Descărcări de astăzi</i> " "numărul de ordine ar fi resetate." -#: rapid/glade3/rapid.glade.h:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." @@ -1920,43 +1514,43 @@ msgstr "" "Specificaţi dacă foto, video şi nume de dosar ar trebui să aibă caractere " "eliminate care nu sunt permise de alte sisteme de operare." -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "Pornire descărcare la pornirea programului" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" msgstr "Pornire descărcare la introducerea dispozitivului" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Număr stocare:" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Curăță caractere incompatibile" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Sincronizarea RAW + JPEG numere de secvenţă" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" msgstr "Demontează (\"scoate\") dispozitiv dacă descărcarea este complectă" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Dosare Video" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" msgstr "Redenumire Video" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" msgstr "Nume dosar copie de siguranță video:" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." @@ -1965,7 +1559,7 @@ msgstr "" "alegeţi dacă să săriţi descărcarea fişierul, sau pentru a adăuga un " "identificator unic." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." @@ -1973,7 +1567,7 @@ msgstr "" "Când copiați de siguranță, alegeți dacă să suprascrieți un fișier de pe " "dispozitivul de rezervă care are acelși nume, sau să-l săriți." -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." @@ -1981,70 +1575,686 @@ msgstr "" "Puteţi avea fotografiile şi video copiate de siguranță în mai multe locaţii " "în care sunt descărcate, de exemplu, hard diskuri externe." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Adaugă..." -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Curăță descărcările Complected" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Importați fotografii și video eficien și fiabil" -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Dispozitiv" +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Resetarea la miezul nopţii\n" -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "_Erori Jurnal" +#~ msgid "Download cannot proceed" +#~ msgstr "Descărcarea nu poate continua" -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Fişier" +#~ msgid "The following download path could not be created:\n" +#~ msgstr "Următoarea cale de descărcare nu a putut fi creată:\n" -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "_Fișier nume" +#~ msgid "There is an error in the program preferences." +#~ msgstr "Este o eroare în preferințe program." -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Găsiți Ajutor Online..." +#~ msgid "errors" +#~ msgstr "erori" -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "_Ajutor" +#, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Sursă: %s\n" -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Faceți o Donație..." +#~ msgid "Error:" +#~ msgstr "Eroare:" -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Cale" +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Destinație: %s" -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "_Previzualizare" +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Dispozitiv: %s\n" -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Raportați o problemă..." +#~ msgid "Photo has already been downloaded" +#~ msgstr "Fotografia este deja descărcată" -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Selectați" +#, python-format +#~ msgid "Attempting to download %s files" +#~ msgstr "Aștept să descarc %s fișiere" -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "_Mărime" +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Descărcarea a început de la %s" -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Tradu această aplicație..." +#~ msgid "No suitable backup volume was found" +#~ msgstr "N-am găsit nici un volum de rezervă adecvat" -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Tip" +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Nu pot șterge fotografii sau video din dispozitiv" -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "_Vizualizează" +#, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Descărcare complectă din %s" + +#~ msgid "_Show this message again" +#~ msgstr "_Arată acest mesaj din nou" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "Descărcarea direct din aparat s-ar putea să lucreze slab sau deloc" + +#~ msgid "" +#~ "Downloading from a card reader always works and is generally much faster. It " +#~ "is strongly recommended to use a card reader." +#~ msgstr "" +#~ "Descărcarea de la un cititor de card funcţionează întotdeauna şi este, în " +#~ "general, mult mai rapid. Este recomandat să utilizaţi un cititor de card." + +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "" +#~ "Acest dispozitiv sau partiţie va fi întotdeauna folosit pentru a descărca de " +#~ "la" + +#~ msgid "Status" +#~ msgstr "Status" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "" +#~ "Acest dispozitiv sau partiţie nu va fi folosit pentru a descărca de la" + +#~ msgid "Path" +#~ msgstr "Cale" + +#~ msgid "Date" +#~ msgstr "Dată" + +#~ msgid "File" +#~ msgstr "Fișier" + +#~ msgid "Type" +#~ msgstr "Tip" + +#~ msgid "Problem with Download Folders" +#~ msgstr "Probleme cu Dosarele de Descărcare" + +#~ msgid "Displaying warning about downloading directly from camera" +#~ msgstr "Afişarea avertisment despre descărcarea direct de la aparat" + +#~ msgid "Some preferences will be reset." +#~ msgstr "Câteva preferințe vor fi resetate." + +#~ msgid "Problem with Download Folder" +#~ msgstr "Probleme cu Dosarul de Descărcare" + +#~ msgid "Problem with Device Location Folder" +#~ msgstr "Problemă cu Locația Dosarului Dispozitivului" + +#~ msgid "" +#~ "A newer version of this program was previously run on this computer.\n" +#~ "\n" +#~ msgstr "" +#~ "O versiune mai nouă a acestui program a fost anterior executa pe acest " +#~ "computer.\n" +#~ "\n" + +#~ msgid "Starting downloads" +#~ msgstr "Pornire descărcări" + +#~ msgid "Warning:" +#~ msgstr "Atenție:" + +#~ msgid "No preferences needed to be changed." +#~ msgstr "Nicio preferință nu trebuie modificată." + +#~ msgid "Preferences were modified." +#~ msgstr "Preferințele au fost modificate" + +#~ msgid "Using manually specified path" +#~ msgstr "Utilizând o cale specificată manual" + +#~ msgid "Automatically start download is false" +#~ msgstr "Pornirea descărcării în mod automat este falsă" + +#~ msgid "Automatically start download is true" +#~ msgstr "Pornirea descărcării în mod automat este adevărată" + +#~ msgid "and" +#~ msgstr "și" + +#~ msgid "MB/s" +#~ msgstr "MB/s" + +#~ msgid "D_ownload Selected" +#~ msgstr "D_escărcări Selectate" + +#~ msgid "All downloads complete" +#~ msgstr "Toate descărcările complecte" + +#~ msgid "_Pause" +#~ msgstr "_Pauză" + +#~ msgid "_Resume" +#~ msgstr "_Reluare" + +#~ msgid "Goodbye" +#~ msgstr "La revedere" + +#~ msgid "Download folder preferences were changed." +#~ msgstr "Descarcă preferințele dosarului după modificare." + +#~ msgid "_Download All" +#~ msgstr "_Descarcă Tot" + +#~ msgid "Using" +#~ msgstr "utilizând" + +#~ msgid "\n" +#~ msgstr "\n" + +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s este deja în execuţie" + +#~ msgid "These preferences are not well formed:" +#~ msgstr "Aceste preferinţe nu sunt bine formate:" + +#~ msgid " " +#~ msgstr " " + +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "" +#~ "Copy text \t\r\n" +#~ "<span weight=\"bold\" size=\"x-large\">Automatizare</span>" + +#~ msgid "Automation" +#~ msgstr "Automatizare" + +#~ msgid "Exit program if download completes without any warnings or errors" +#~ msgstr "" +#~ "Ieși din program dacă descărcarea este complectă fără atenționări și erori" + +#~ msgid "Error Log" +#~ msgstr "Jurnal Erori" + +#~ msgid "Select All Vi_deos" +#~ msgstr "Selectați toate Vi_deo" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Selectați toate Fo_tografiile" + +#~ msgid "Select _All" +#~ msgstr "Selectează _tot" + +#~ msgid "_Device" +#~ msgstr "_Dispozitiv" + +#~ msgid "_Path" +#~ msgstr "_Cale" + +#~ msgid "_Preview" +#~ msgstr "_Previzualizare" + +#~ msgid "_Report a Problem..." +#~ msgstr "_Raportați o problemă..." + +#~ msgid "_Size" +#~ msgstr "_Mărime" + +#~ msgid "Could not create temporary download directory" +#~ msgstr "Nu am putut crea directorul temporar de descărcare" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Calea %s nu poate fi creată" + +#, python-format +#~ msgid "Source: %(source)s" +#~ msgstr "Sursă: %(source)s" + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Directorul de destinație nu poate fi creat: %(directory)s\n" + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Erori: %(inst)s" + +#~ msgid "A backup location was not found" +#~ msgstr "Locația copiei de rezervă nu a fost găsită" + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s sunt deja descărcate" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s vor fi descărcate cu avertizări" + +#, python-format +#~ msgid "%(filetype)s is about to be downloaded" +#~ msgstr "%(filetype)s vor fi descărcate" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s nu au fost descărcate" + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s a fost descărcate cu succes" + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s au fost descărcate cu avertizări" + +#, python-format +#~ msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#~ msgstr "Dosarul %(file_type)s de Descărcări există dar nu poate fi scris.\n" + +#, python-format +#~ msgid "The %(file_type)s Download Folder does not exist.\n" +#~ msgstr "Dosarul %(file_type)s de Descărcări nu există.\n" + +#, python-format +#~ msgid "Creating photo download folder %(folder)s" +#~ msgstr "Crearea Dosarului de descărcare fotografii %(folder)s" + +#, python-format +#~ msgid "Creating video download folder %(folder)s" +#~ msgstr "Crearea dosarului de descărcări video %(folder)s" + +#, python-format +#~ msgid "About %(minutes)i:%(seconds)02i minutes remaining" +#~ msgstr "Aproximativ %(minutes)i:%(seconds)-2i minute rămân" + +#~ msgid "About 1 minute remaining" +#~ msgstr "Aprozimativ 1 minut rămâne" + +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Dispozitiv %(device)s (%(path)s) ignorat" + +#, python-format +#~ msgid "%(filetype)s downloaded" +#~ msgstr "%(filetype)s descărcate" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Detectat %(device)s cu calea %(path)s" + +#, python-format +#~ msgid "About %i seconds remaining" +#~ msgstr "Aproximativ %i secunde rămân" + +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "Valoare preferință %(value)s' este invalidă" + +#~ msgid "Se_lect None" +#~ msgstr "Se_lectat Nimic" + +#~ msgid "Preview _Folders" +#~ msgstr "Previzualizare _Dosare" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s" +#~ msgstr "" +#~ "Sursă: %(source)s\n" +#~ "Destinație: %(destination)s" + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Sursă: %(source)s\n" +#~ "Detinație: %(destination)s\n" +#~ "%(problem)s" + +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s selectate pentru descărcare de la" + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Fotografie: %(source)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Fotografie: %(source)s\n" +#~ "Eroare: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "Șterse %(number)i %(filetypes)s din dispozitiv" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s nu pot fi descărcate" + +#, python-format +#~ msgid "Failed to create default video download folder %(folder)s" +#~ msgstr "Nu am reușit să creez dosar descărcare video %(folder)s" + +#, python-format +#~ msgid "Failed to create default photo download folder %(folder)s" +#~ msgstr "Nu am reușit să creez dosar descărcare fotografii %(folder)s" + +#, python-format +#~ msgid "%(free)s available" +#~ msgstr "%(free)s disponibile" + +#, python-format +#~ msgid "%(number)s %(numberdownloaded)s" +#~ msgstr "%(number)s %(numberdownloaded)s" + +#, python-format +#~ msgid "%(filetype)s failed to download" +#~ msgstr "%(filetype)s au eşuat la descărcare" + +#~ msgid "Download device settings preferences were changed." +#~ msgstr "Setări preferințe descărcare din dispozitiv au fost schimbate." + +#~ msgid "P_review Columns" +#~ msgstr "P_revizualizare Coloane" + +#, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "Scanare dispozitiv complectă: nu sunt %(filetypes)s în %(device)s" + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Scanare dispozitiv complectă: găsite %(number)s %(filetypes)s în %(device)s" + +#, python-format +#~ msgid "%(noFiles)s %(filetypes)s downloaded" +#~ msgstr "%(noFiles)s %(filetypes)s descărcate" + +#~ msgid "Backup path does not exist" +#~ msgstr "Calea copiei de siguranță nu există" + +#, python-format +#~ msgid "%(noFiles)s %(filetypes)s failed to download" +#~ msgstr "%(noFiles)s %(filetypes)s descărcare eșuată" + +#, python-format +#~ msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" +#~ msgstr "%(number)s din %(total)s %(filetypes)s (%(remaining)s remaining)" + +#, python-format +#~ msgid "This device has no %(types_searched_for)s to download from." +#~ msgstr "" +#~ "Acest dispozitiv nu are %(types_searched_for)s pentru a fi descărcate." + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Eroare: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "%(file_type)s could not be backed up" +#~ msgstr "%(file_type)s nu pot fi copiate în siguranță" + +#, python-format +#~ msgid "%(filetype)s was downloaded but there were problems backing up" +#~ msgstr "" +#~ "%(filetype)s au fost descărcate dar sunt probleme pentru copieri de siguranță" + +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Determinați dacă doriţi să utilizaţi %s" + +#~ msgid "No backup devices detected" +#~ msgstr "Nu am găsit copie de siguranță a dispozitivului" + +#~ msgid "Using backup device" +#~ msgstr "Folosesc copia de siguranță a dispozitivului" + +#~ msgid "Using backup devices" +#~ msgstr "Folosesc copia de siguranță a dispozitivelor" + +#~ msgid "Backup preferences were changed." +#~ msgstr "Preferințele copiei de siguranță au fost schimbate." + +#, python-format +#~ msgid "" +#~ "Preference key '%(key)s' is invalid.\n" +#~ "Expected one of %(value)s" +#~ msgstr "" +#~ "Preferința cheii '%(key)s' este invalidă\n" +#~ "Aștept una dintre %(value)s" + +#~ msgid "Subfolder and filename preferences were changed." +#~ msgstr "Preferințele subdosarului și numelui fișier au fost schimbate." + +#~ 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 este software liber, îl puteţi redistribui şi / sau " +#~ "modifica sub termenii GNU General Public License publicate de Free Software " +#~ "Foundation; fie versiunea 2 a Licenţei, sau (la opţiunea dumneavoastră) " +#~ "orice versiune ulterioară.\n" +#~ "\n" +#~ "Rapid Photo Downloader este distribuit în speranţa că va fi folositor, dar " +#~ "FĂRĂ NICI O GARANŢIE, nici chiar garanţia implicită de VANDABILITATE sau " +#~ "POTRIVIRE PENTRU UN SCOP ANUME. Vezi GNU General Public License pentru mai " +#~ "multe detalii.\n" +#~ "\n" +#~ "Trebuie să fi primit o copie a GNU General Public License, împreună cu Rapid " +#~ "Photo Downloader, dacă nu, scrieţi la Free Software Foundation, Inc, 51 " +#~ "Franklin Street, Fifth Floor, Boston, MA 02110 la 1301, Statele Unite ale " +#~ "Americii." + +#~ msgid "_Get Help Online..." +#~ msgstr "_Găsiți Ajutor Online..." + +#~ msgid "_Filename" +#~ msgstr "_Fișier nume" + +#~ msgid "_Type" +#~ msgstr "_Tip" + +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Aceste preferințe conțin o eroare:\n" + +#, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "Copia de siguranță %(file_type)s va fi rescrisă" + +#~ msgid "Backing up error" +#~ msgstr "Eroare copiere de siguranță" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s rejectat ca și dispozitiv de descărcare" + +#, python-format +#~ msgid "%(filetype)s was neither downloaded nor backed up" +#~ msgstr "%(filetype)s nu trebuie descărcate sau copiate de siguranță" + +#~ msgid "About 1 second remaining" +#~ msgstr "Aproximativ 1 secundă rămâne" + +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Valoare Invalidă Descărcări Astăzi.\n" + +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "Valorile preferinței 'Pornirea zilei' sunt corupte.\n" + +#~ msgid "warnings" +#~ msgstr "avertismente" + +#~ msgid "No backups can occur" +#~ msgstr "Copii de siguranță nu pot avea loc" + +#, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "%(file_type)s nu s-a copiat de siguranță în %(volume)s" + +#, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Copia de siguranță a %(file_type)s există deja" + +#, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "%(file_type)s nu s-a copiat de siguranță" + +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "" +#~ "Nouă zi a început - resetați numărul de secvență \"Descărcările de azi\"" + +#, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "Acest %(file_type)s nu s-a creat în copia de siguranță." + +#~ msgid "Job Code not entered" +#~ msgstr "Codul Sarcină nu s-a introdus" + +#~ msgid "Job Code entered" +#~ msgstr "Cod Sarcină introdus" + +#~ msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#~ msgstr "Introduceți un nou Cod Sarcină, sau selectați unul existent" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "Ponesc descărcarea care așteaptă un Cod Sarcină" + +#~ msgid "Prompting for Job Code" +#~ msgstr "Determinați pentru Cod Sarcină" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Deja determinat pentru Cod Sarcină, nu solicita din nou" + +#~ msgid "Problem using pynotify." +#~ msgstr "Probleme folosind notificarea py." + +#, python-format +#~ msgid "Warning: backup device %(device)s is currently being downloaded from" +#~ msgstr "" +#~ "Atenție: copia de siguranță a dispozitivului %(device)s este în curs de " +#~ "descărcare de pe" + +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Copyright Damon Lynch 2007-10" + +#~ msgid "Job Code" +#~ msgstr "Cod Sarcină" + +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Valoare număr stocare nu a fost actualizat, pentru că o descărcare are loc " +#~ "în prezent" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Valoare descărcări de astăzi nu a fost actualizată, pentru că o descărcare " +#~ "are loc în prezent" + +#, python-format +#~ msgid "" +#~ "The %(filetype)s subfolder preferences had some unnecessary values removed." +#~ msgstr "" +#~ "Preferințele subdosarului %(filetype)s au fost șterse câteva valori inutile." + +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Verificați preferințele, reporniți, și încercați din nou." + +#~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "Preferinţele programului par a fi valabil, verificaţi pentru a asigura " +#~ "funcţionarea corectă." + +#~ msgid "Please check your system and try again." +#~ msgstr "Verificați-vă sistemul și încercați din nou." + +#~ 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 "" +#~ "Această versiune de program folosește preferințe diferite decât versiunea " +#~ "veche. Preferințele dvs. au fost actualizate.\n" +#~ "\n" +#~ "Verificaţi-le pentru a asigura funcţionarea corectă." + +#, python-format +#~ msgid "" +#~ "Sorry, this device location does not exist:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Please resolve the problem, or modify your preferences." +#~ msgstr "" +#~ "Locația dispozitivului nu există:\n" +#~ "%(path)s\n" +#~ "Rezolvaţi problema, sau modificați preferinţele dvs." + +#~ msgid "" +#~ "Sorry, problems were encountered with your download folders. Please fix the " +#~ "problems or modify the preferences.\n" +#~ "\n" +#~ msgstr "" +#~ "Probleme au fost întâmpinate cu dosarele de descărcare. Corectaţi problemele " +#~ "sau să modificați preferinţele.\n" +#~ "\n" + +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "Unele preferinţe sunt invalide şi vor fi resetate." + +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Se resetează valore la zero.\n" + +#~ msgid "Resetting to default values." +#~ msgstr "Se resetează la valori implicite." + +#~ msgid "The device can now be safely removed" +#~ msgstr "Dispozitivul poate fi scos în siguranță" + +#~ msgid "Downloading From Cameras" +#~ msgstr "Descărcarea din Aparat" + +#~ msgid "" +#~ "This version of the program is newer than the previously run version. " +#~ "Checking preferences." +#~ msgstr "" +#~ "Această versiune a programului este mai nouă decât versiunea anterioară ce " +#~ "rulează. Verificați preferinţele." + +#~ 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 "" +#~ "Această versiune de program folosește preferințe diferite decât versiunea " +#~ "veche. Câteva din preferințe sunt invalide și nu pot fi actualizate. Ele vor " +#~ "fi resetate." + +#~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Avertizare: mediul desktop este configurat incorect pentru notificare server." @@ -7,247 +7,22 @@ msgid "" msgstr "" "Project-Id-Version: rapid\n" "Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n" -"POT-Creation-Date: 2010-12-28 02:49-0600\n" -"PO-Revision-Date: 2010-12-31 06:58+0000\n" +"POT-Creation-Date: 2011-04-10 19:59-0500\n" +"PO-Revision-Date: 2011-04-15 18:27+0000\n" "Last-Translator: Sergey 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: 2011-03-20 22:12+0000\n" -"X-Generator: Launchpad (build 12617)\n" +"X-Launchpad-Export-Date: 2011-04-21 06:12+0000\n" +"X-Generator: Launchpad (build 12883)\n" #. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html -#: rapid/rapid.py:124 rapid/rapid.py:6468 rapid/glade3/rapid.glade.h:71 +#: rapid/rapid.py:104 rapid/glade3/rapid.ui.h:11 msgid "Rapid Photo Downloader" msgstr "Rapid Photo Downloader" -#: rapid/rapid.py:461 -msgid "New York" -msgstr "Нью-Йорк" - -#: rapid/rapid.py:462 -msgid "Manila" -msgstr "Манила" - -#: rapid/rapid.py:462 -msgid "Prague" -msgstr "Прага" - -#: rapid/rapid.py:462 -msgid "Helsinki" -msgstr "Хельсинки" - -#: rapid/rapid.py:462 -msgid "Wellington" -msgstr "Веллингтон" - -#: rapid/rapid.py:463 -msgid "Tehran" -msgstr "Тегеран" - -#: rapid/rapid.py:463 -msgid "Kampala" -msgstr "Кампала" - -#: rapid/rapid.py:463 -msgid "Paris" -msgstr "Париж" - -#: rapid/rapid.py:463 -msgid "Berlin" -msgstr "Берлин" - -#: rapid/rapid.py:463 -msgid "Sydney" -msgstr "Сидней" - -#: rapid/rapid.py:464 -msgid "Budapest" -msgstr "Будапешт" - -#: rapid/rapid.py:464 -msgid "Rome" -msgstr "Рим" - -#: rapid/rapid.py:464 -msgid "Moscow" -msgstr "Москва" - -#: rapid/rapid.py:464 -msgid "Delhi" -msgstr "Дели" - -#: rapid/rapid.py:464 -msgid "Warsaw" -msgstr "Варшава" - -#: rapid/rapid.py:465 -msgid "Jakarta" -msgstr "Джакарта" - -#: rapid/rapid.py:465 -msgid "Madrid" -msgstr "Мадрид" - -#: rapid/rapid.py:465 -msgid "Stockholm" -msgstr "Стокгольм" - -#: rapid/rapid.py:499 -msgid "Invalid Downloads Today value.\n" -msgstr "Неверное значение 'Загрузок сегодня'.\n" - -#: rapid/rapid.py:500 -msgid "Resetting value to zero.\n" -msgstr "Сбросить значение до нуля.\n" - -#: rapid/rapid.py:539 -msgid "'Start of day' preference value is corrupted.\n" -msgstr "Значение 'Начало дня' повреждено.\n" - -#: rapid/rapid.py:540 -msgid "Resetting to midnight.\n" -msgstr "Вернуть значение \"полночь\".\n" - -#: rapid/rapid.py:566 -msgid "Error in Photo Rename preferences" -msgstr "Ошибка в параметрах Переименования фото" - -#: rapid/rapid.py:598 rapid/rapid.py:1720 -msgid "Sorry,these preferences contain an error:\n" -msgstr "Извините, эти параметры содержат ошибку:\n" - -#: rapid/rapid.py:609 -msgid "Resetting to default values." -msgstr "Восстановить настройки по умолчанию." - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:684 rapid/renamesubfolderprefs.py:198 -msgid "Job code" -msgstr "Метка" - -#: rapid/rapid.py:752 -msgid "Error in Video Rename preferences" -msgstr "Ошибка в параметрах Переименования видео" - -#: rapid/rapid.py:770 -msgid "Error in Photo Download Subfolders preferences" -msgstr "Ошибка в параметрах Подкаталогов для загрузки фото" - -#: rapid/rapid.py:787 -msgid "Error in Video Download Subfolders preferences" -msgstr "Ошибка в параметрах Подкаталогов для загрузки видео" - -#: rapid/rapid.py:820 rapid/rapid.py:1551 -msgid "photos and videos" -msgstr "фото и видео" - -#: rapid/rapid.py:822 rapid/rapid.py:1561 rapid/rapid.py:1689 -msgid "photos" -msgstr "фото" - -#: rapid/rapid.py:955 -msgid "Select a folder to download photos to" -msgstr "Выберите каталог для загрузки фото" - -#: rapid/rapid.py:973 -msgid "Select a folder to download videos to" -msgstr "Выберите каталог для загрузки видео" - -#: rapid/rapid.py:1055 -#, python-format -msgid "Select a folder containing %(file_types)s" -msgstr "Выберите каталог, содержащий %(file_types)s" - -#: rapid/rapid.py:1077 -#, python-format -msgid "Select a folder in which to backup %(file_types)s" -msgstr "" -"Выберите каталог в котором будут храниться резервные копии %(file_types)s" - -#. 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:1158 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate the " -"name. Please use other renaming options.</i>" -msgstr "" -"<i><b>Внимание:</b> Недостаточно метаданных для создания имен файлов. " -"Пожалуйста, используйте другие варианты переименования.</i>" - -#: rapid/rapid.py:1194 -msgid "" -"<i><b>Warning:</b> There is insufficient metadata to fully generate " -"subfolders. Please use other subfolder naming options.</i>" -msgstr "" -"<i><b>Warning:</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:1198 -#, python-format -msgid "<i>Example: %s</i>" -msgstr "<i>Пример: %s</i>" - -#: rapid/rapid.py:1224 -msgid "" -"Downloads today value not updated, as a download is currently occurring" -msgstr "" -"Значение \"Загрузок сегодня\" не обновлено, так как загрузка идёт прямо " -"сейчас" - -#: rapid/rapid.py:1240 -msgid "Stored number value not updated, as a download is currently occurring" -msgstr "" -"Счетчик сквозной нумерации не обновлен, так как прямо сейчас идёт загрузка" - -#: rapid/rapid.py:1270 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences had some unnecessary values removed." -msgstr "Некоторые излишние настройки подкаталога %(filetype)s удалены." - -#. Preferences list is now empty -#: rapid/rapid.py:1275 -#, python-format -msgid "" -"The %(filetype)s subfolder preferences entered are invalid and cannot be " -"used.\n" -"They will be reset to their default values." -msgstr "" -"Введённые настройки подкаталога для %(filetype)s неверны и не могут быть " -"использованы.\n" -"Они сброшены до значений по умолчанию." - -#. check subfolder preferences for bad values -#: rapid/rapid.py:1289 rapid/rapid.py:1563 -msgid "photo" -msgstr "фото" - -#: rapid/rapid.py:1290 rapid/rapid.py:1558 -msgid "video" -msgstr "видео" - -#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. -#: rapid/rapid.py:1527 -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:1529 -msgid "externaldrive2" -msgstr "внешнийдиск2" - -#: rapid/rapid.py:1553 rapid/rapid.py:1687 -msgid "photos or videos" -msgstr "фото или видео" - -#: rapid/rapid.py:1556 -msgid "videos" -msgstr "видео" - -#: rapid/rapid.py:1568 +#: rapid/rapid.py:109 #, python-format msgid "" "%(date)s\n" @@ -256,825 +31,258 @@ msgstr "" "%(date)s\n" "%(time)s" -#: rapid/rapid.py:1570 +#: rapid/rapid.py:111 #, python-format msgid "%(date)s %(time)s" msgstr "%(date)s %(time)s" -#: rapid/rapid.py:1573 -#, python-format -msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" -msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" - -#: rapid/rapid.py:1580 +#: rapid/rapid.py:114 #, python-format msgid "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" msgstr "%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s" -#: rapid/rapid.py:1608 rapid/rapid.py:2280 -msgid "subfolder and filename" -msgstr "подкаталог и название файла" +#. Device refers to a thing like a camera, memory card in its reader, +#. external hard drive, Portable Storage Device, etc. +#: rapid/rapid.py:148 +msgid "Device" +msgstr "Носитель" -#: rapid/rapid.py:1610 rapid/rapid.py:2282 -msgid "filename" -msgstr "имя файла" +#. Size refers to the total size of images on the device, typically in +#. MB or GB +#: rapid/rapid.py:165 +msgid "Size" +msgstr "Размер" -#: rapid/rapid.py:1612 rapid/rapid.py:2284 -msgid "subfolder" -msgstr "подкаталог" +#: rapid/rapid.py:168 +msgid "Download Progress" +msgstr "Ход загрузки" + +#: rapid/rapid.py:312 +#, python-format +msgid "%(device)s did not unmount" +msgstr "" #. This refers to when a device like a hard drive is having its contents scanned, #. looking for photos or videos. It is visible initially in the progress bar for each device #. (which normally holds "x photos and videos"). #. It maybe displayed only briefly if the contents of the device being scanned is small. -#: rapid/rapid.py:1703 +#: rapid/rapid.py:1091 msgid "scanning..." msgstr "сканирование..." -#: rapid/rapid.py:1818 -msgid "The following download path could not be created:\n" -msgstr "Указанный путь для загрузки файлов не может быть создан:\n" - -#: rapid/rapid.py:1819 -#, python-format -msgid "%(path)s: " -msgstr "%(path)s: " - -#: rapid/rapid.py:1820 rapid/rapid.py:1821 rapid/rapid.py:1836 -#: rapid/rapid.py:1837 rapid/rapid.py:2097 rapid/rapid.py:2100 -msgid "Download cannot proceed" -msgstr "Невозможно загрузить" +#: rapid/rapid.py:1807 +msgid "Download" +msgstr "Загрузка" -#: rapid/rapid.py:1834 rapid/rapid.py:5105 -msgid "There is an error in the program preferences." -msgstr "Обнаружена ошибка в настройках программы." +#: rapid/rapid.py:1810 +msgid "Pause" +msgstr "Пауза" -#: rapid/rapid.py:1835 -msgid "" -"\n" -"Please check preferences, restart the program, and try again." -msgstr "" -"\n" -"Пожалуйста, проверьте настройки, перезапустите программу и попробуйте снова." - -#. 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 photos that can be copied. For example, the user might see the following: -#. '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. -#. This particular text is displayed to the user before the download has started. -#: rapid/rapid.py:2008 -#, python-format -msgid "%(number)s %(filetypes)s" -msgstr "%(number)s %(filetypes)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 photos 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:2019 -#, python-format -msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" -msgstr "" -"Сканирование носителя завершено: найдено %(number)s %(filetypes)s на " -"%(device)s" - -#: rapid/rapid.py:2026 -#, python-format -msgid "Device scan complete: no %(filetypes)s found on %(device)s" -msgstr "" -"Сканирование носителя завершено: %(filetypes)s не найдено на %(device)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:2047 -msgid "The device can now be safely removed" -msgstr "Теперь можно безопасно отсоединить носитель" - -#: rapid/rapid.py:2053 -#, python-format -msgid "%(noFiles)s %(filetypes)s downloaded" -msgstr "%(noFiles)s %(filetypes)s загружено" - -#: rapid/rapid.py:2056 -#, python-format -msgid "%(noFiles)s %(filetypes)s failed to download" -msgstr "%(noFiles)s %(filetypes)s не удалось загрузить" - -#: rapid/rapid.py:2059 rapid/rapid.py:5901 -msgid "warnings" -msgstr "предупреждения" - -#: rapid/rapid.py:2061 rapid/rapid.py:5905 -msgid "errors" -msgstr "ошибки" - -#: rapid/rapid.py:2091 -#, python-format -msgid "Source: %s\n" -msgstr "Источник: %s\n" - -#: rapid/rapid.py:2093 -#, python-format -msgid "Device: %s\n" -msgstr "Носитель: %s\n" - -#: rapid/rapid.py:2094 -#, python-format -msgid "Destination: %s" -msgstr "Назначение: %s" - -#: rapid/rapid.py:2095 rapid/rapid.py:2098 -msgid "Could not create temporary download directory" -msgstr "Не удалось создать временный каталог для загрузки" - -#: rapid/rapid.py:2098 -msgid "Error:" -msgstr "Ошибка:" - -#: rapid/rapid.py:2122 -msgid "Backup path does not exist" -msgstr "Путь резервного копирования не существует" - -#: rapid/rapid.py:2123 -#, python-format -msgid "The path %s could not be created" -msgstr "Не удалось создать путь %s" - -#: rapid/rapid.py:2124 -msgid "No backups can occur" -msgstr "Резервное копирование невозможно" - -#: rapid/rapid.py:2153 +#: rapid/rapid.py:1912 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s\n" -"%(problem)s" +"These download folders are invalid:\n" +"%(folder1)s\n" +"%(folder2)s" msgstr "" -"Источник: %(source)s\n" -"Назначение: %(destination)s\n" -"%(problem)s" -#: rapid/rapid.py:2184 rapid/rapid.py:2530 rapid/rapid.py:2565 -#: rapid/rapid.py:2593 rapid/rapid.py:2624 rapid/rapid.py:2643 +#: rapid/rapid.py:1915 #, python-format msgid "" -"Source: %(source)s\n" -"Destination: %(destination)s" +"This download folder is invalid:\n" +"%s" msgstr "" -"Источник: %(source)s\n" -"Назначение: %(destination)s" - -#. hopefully inst will never be None, but just to be safe... -#: rapid/rapid.py:2199 -msgid "Please check your system and try again." -msgstr "Пожалуйста, проверьте вашу систему и попробуйте снова." -#: rapid/rapid.py:2219 -msgid "Photos detected with the same filenames, but taken at different times" -msgstr "" -"Обнаружены фотографии с одинаковыми названиями, но сделанные в разное время" +#: rapid/rapid.py:1916 +msgid "Download cannot proceed" +msgstr "Невозможно загрузить" -#: rapid/rapid.py:2259 -msgid "Photo has already been downloaded" -msgstr "Фото уже загружено" +#: rapid/rapid.py:2130 +msgid "About 1 second remaining" +msgstr "Осталась примерно 1 секунда" -#: rapid/rapid.py:2260 rapid/rapid.py:2659 +#: rapid/rapid.py:2132 #, python-format -msgid "Source: %(source)s" -msgstr "Источник: %(source)s" - -#. A new day, according the user's preferences of what time a day begins, has started -#: rapid/rapid.py:2458 -msgid "New day has started - resetting 'Downloads Today' sequence number" -msgstr "" -"Начался новый день - сброшена последовательность номеров параметра 'Загрузок " -"сегодня'" +msgid "About %i seconds remaining" +msgstr "Осталось %i секунд" -#: rapid/rapid.py:2529 -#, python-format -msgid "Backup of %(file_type)s already exists" -msgstr "Резервная копия %(file_type)s уже существует" +#: rapid/rapid.py:2134 +msgid "About 1 minute remaining" +msgstr "Осталась примерно 1 минута" -#: rapid/rapid.py:2533 +#. 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:2139 #, python-format -msgid "Backup %(file_type)s overwritten" -msgstr "Резервная копия %(file_type)s перезаписана" +msgid "About %(minutes)i:%(seconds)02i minutes remaining" +msgstr "Осталось примерно %(minutes)i:%(seconds)02i" -#: rapid/rapid.py:2537 -#, python-format -msgid "%(file_type)s not backed up to %(volume)s" -msgstr "%(file_type)s не скопирован в резервную копию на %(volume)s" +#: rapid/rapid.py:2151 rapid/preferencesdialog.py:822 rapid/rpdfile.py:110 +msgid "photos and videos" +msgstr "фото и видео" -#: rapid/rapid.py:2539 -#, python-format -msgid "%(file_type)s not backed up" -msgstr "%(file_type)s не скопирован в резервную копию" +#: rapid/rapid.py:2153 rapid/rpdfile.py:112 +msgid "photos or videos" +msgstr "фото или видео" -#: rapid/rapid.py:2562 rapid/rapid.py:2590 rapid/rapid.py:2623 -#: rapid/rapid.py:2642 -msgid "Backing up error" -msgstr "Ошибка резервного копирования" +#: rapid/rapid.py:2156 rapid/rapid.py:2661 rapid/rpdfile.py:115 +msgid "videos" +msgstr "видео" -#: rapid/rapid.py:2563 rapid/rapid.py:2591 -#, python-format -msgid "Destination directory could not be created: %(directory)s\n" -msgstr "Каталог назначения не может быть создан: %(directory)s\n" +#: rapid/rapid.py:2158 rapid/preferencesdialog.py:1371 rapid/rpdfile.py:117 +#: rapid/rpdfile.py:266 +msgid "video" +msgstr "видео" -#: rapid/rapid.py:2567 rapid/rapid.py:2626 -#, python-format -msgid "Error: %(inst)s" -msgstr "Ошибка: %(inst)s" +#: rapid/rapid.py:2161 rapid/rapid.py:2659 rapid/preferencesdialog.py:824 +#: rapid/rpdfile.py:120 +msgid "photos" +msgstr "фото" -#: rapid/rapid.py:2568 rapid/rapid.py:2596 rapid/rapid.py:2627 -#: rapid/rapid.py:2646 -#, python-format -msgid "The %(file_type)s was not backed up." -msgstr "Резервная копия %(file_type)s не была создана." +#. check subfolder preferences for bad values +#: rapid/rapid.py:2163 rapid/preferencesdialog.py:1370 rapid/rpdfile.py:122 +#: rapid/rpdfile.py:246 +msgid "photo" +msgstr "фото" -#: rapid/rapid.py:2595 rapid/rapid.py:2645 +#: rapid/rapid.py:2188 #, python-format -msgid "Error: %(errno)s %(strerror)s" -msgstr "Ошибка: %(errno)s %(strerror)s" +msgid "%(noFiles)s %(filetypes)s downloaded" +msgstr "%(noFiles)s %(filetypes)s загружено" -#: rapid/rapid.py:2658 +#: rapid/rapid.py:2192 #, python-format -msgid "%(file_type)s could not be backed up" -msgstr "Резервная копия %(file_type)s не может быть создана." - -#: rapid/rapid.py:2661 -msgid "No suitable backup volume was found" -msgstr "Не найдено подходящего раздела для сохранения резервных копий" +msgid "%(noFiles)s %(filetypes)s failed to download" +msgstr "%(noFiles)s %(filetypes)s не удалось загрузить" -#: rapid/rapid.py:2663 -msgid "A backup location was not found" -msgstr "Не найдено указанное размещение для сохранения резервных копий" +#: rapid/rapid.py:2195 rapid/rapid.py:2247 +msgid "warnings" +msgstr "предупреждения" -#: rapid/rapid.py:2717 -#, python-format -msgid "This device has no %(types_searched_for)s to download from." -msgstr "Носитель не содержит %(types_searched_for)s для загрузки." +#: rapid/rapid.py:2204 +msgid "All downloads complete" +msgstr "Все загрузки завершены" -#: rapid/rapid.py:2813 +#: rapid/rapid.py:2210 rapid/rapid.py:2219 rapid/rapid.py:2228 +#: rapid/rapid.py:2237 rapid/rapid.py:2245 #, python-format -msgid "Download has started from %s" -msgstr "Начата загрузка с %s" +msgid "%(number)s %(numberdownloaded)s" +msgstr "%(number)s %(numberdownloaded)s" -#: rapid/rapid.py:2817 +#: rapid/rapid.py:2212 rapid/rapid.py:2230 #, python-format -msgid "Attempting to download %s files" -msgstr "Попытка загрузить %s файлов" +msgid "%(filetype)s downloaded" +msgstr "%(filetype)s загружено" -#. reset the progress bar to update the status of this download attempt -#: rapid/rapid.py:2849 rapid/rapid.py:2917 +#: rapid/rapid.py:2221 rapid/rapid.py:2239 #, python-format -msgid "%(number)s of %(total)s %(filetypes)s" -msgstr "%(number)s из %(total)s %(filetypes)s" +msgid "%(filetype)s failed to download" +msgstr "%(filetype)s не удалось загрузить" -#: rapid/rapid.py:2913 +#. e.g.: 3 of 205 photos and videos (202 remaining) +#: rapid/rapid.py:2276 #, python-format msgid "%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)" msgstr "%(number)s из %(total)s %(filetypes)s (%(remaining)s осталось)" -#: rapid/rapid.py:2938 rapid/rapid.py:2942 -msgid "Could not delete photo or video from device" -msgstr "Не удалось удалить фото или видео с носителя" - -#: rapid/rapid.py:2939 +#. e.g.: 205 of 205 photos and videos +#: rapid/rapid.py:2283 #, python-format -msgid "" -"Photo: %(source)s\n" -"Error: %(errno)s %(strerror)s" -msgstr "" -"Фото: %(source)s\n" -"Ошибка: %(errno)s %(strerror)s" +msgid "%(number)s of %(total)s %(filetypes)s" +msgstr "%(number)s из %(total)s %(filetypes)s" -#: rapid/rapid.py:2943 -#, python-format -msgid "Photo: %(source)s" -msgstr "Фото: %(source)s" +#: rapid/rapid.py:2665 +msgid "Free space:" +msgstr "Свободное место:" -#: rapid/rapid.py:2945 +#. (videos) or (photos) will be appended to the free space message displayed to the +#. user in the status bar. +#. you should only translate this if your language does not use parantheses +#: rapid/rapid.py:2677 #, python-format -msgid "Deleted %(number)i %(filetypes)s from device" -msgstr "Удалено %(number)i %(filetypes)s с носителя" +msgid "(%(file_type)s)" +msgstr "" -#: rapid/rapid.py:2958 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#: rapid/rapid.py:2681 #, 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:3073 rapid/rapid.py:3542 -msgid "Device" -msgstr "Носитель" - -#. Size refers to the total size of images on the device, typically in MB or GB -#: rapid/rapid.py:3078 rapid/rapid.py:3531 -msgid "Size" -msgstr "Размер" - -#: rapid/rapid.py:3081 -msgid "Download Progress" -msgstr "Ход загрузки" - -#: rapid/rapid.py:3169 -msgid "Downloading From Cameras" -msgstr "Загрузка с камеры" - -#: rapid/rapid.py:3175 -msgid "Downloading directly from a camera may work poorly or not at all" +msgid "%(free)s %(file_type)s" msgstr "" -"Загрузка непосредственно с камеры может работать плохо или не работать вовсе" -#: rapid/rapid.py:3176 -msgid "" -"Downloading from a card reader always works and is generally much faster. It " -"is strongly recommended to use a card reader." +#. Inserted in the middle of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2686 +msgid "; " msgstr "" -"Загрузка через картридер работает устойчиво и намного быстрее. Настоятельно " -"рекомендуется использовать картридер." - -#: rapid/rapid.py:3190 -msgid "_Show this message again" -msgstr "_Показывать это сообщение снова" - -#: rapid/rapid.py:3225 -msgid "Device Detected" -msgstr "Обнаружен носитель" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3234 -msgid "" -"Should this device or partition be used to download photos or videos from?" -msgstr "Следует ли загрузить фото или видео с этого носителя или раздела?" -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3253 -msgid "_Remember this choice" -msgstr "_Запомнить мой выбор" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3290 -#, python-format -msgid "%s selected for downloading from" -msgstr "%s выбран для загрузки" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3293 -msgid "This device or partition will always be used to download from" -msgstr "Этот носитель или раздел всегда будет использован для загрузки" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3296 -#, python-format -msgid "%s rejected as a download device" -msgstr "%s не выбран для загрузки" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt -#: rapid/rapid.py:3299 -msgid "This device or partition will never be used to download from" -msgstr "Этот носитель или раздел никогда не будет использован для загрузки" - -#: rapid/rapid.py:3306 -msgid "Remove all Job Codes?" -msgstr "Удалить все метки?" - -#: rapid/rapid.py:3323 -msgid "Should all Job Codes be removed?" -msgstr "Вы действительно хотите удалить все метки?" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3351 -msgid "Enter a Job Code" -msgstr "Введите метку" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3370 -msgid "Enter a new Job Code, or select a previous one" -msgstr "Введите новую метку или выберите одну из существующих" - -#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode -#: rapid/rapid.py:3373 -msgid "Enter a new Job Code" -msgstr "Введите новую метку" - -#: rapid/rapid.py:3378 rapid/rapid.py:4640 -msgid "Job Code:" -msgstr "Метка:" - -#: rapid/rapid.py:3425 -msgid "Job Code entered" -msgstr "Метка введена" - -#: rapid/rapid.py:3427 -msgid "Job Code not entered" -msgstr "Метка не введена" - -#: rapid/rapid.py:3477 -msgid "Status" -msgstr "Статус" - -#: rapid/rapid.py:3485 -msgid "Type" -msgstr "Тип" - -#: rapid/rapid.py:3494 rapid/rapid.py:5067 rapid/rapid.py:5069 -msgid "Photo" -msgstr "Фото" - -#: rapid/rapid.py:3496 -msgid "File" -msgstr "Файл" - -#: rapid/rapid.py:3511 -msgid "Job Code" -msgstr "Метка" - -#: rapid/rapid.py:3521 -msgid "Date" -msgstr "Дата" - -#: rapid/rapid.py:3553 rapid/renamesubfolderprefs.py:194 -msgid "Filename" -msgstr "Имя файла" - -#: rapid/rapid.py:3564 -msgid "Path" -msgstr "Путь" - -#: rapid/rapid.py:3974 -#, python-format -msgid "%(filetype)s was downloaded successfully" -msgstr "%(filetype)s успешно загружено" - -#: rapid/rapid.py:3976 -#, python-format -msgid "%(filetype)s was not downloaded" -msgstr "%(filetype)s не загружено" - -#: rapid/rapid.py:3978 -#, python-format -msgid "%(filetype)s was downloaded with warnings" -msgstr "%(filetype)s загружено с ошибками" - -#: rapid/rapid.py:3980 -#, python-format -msgid "%(filetype)s was downloaded but there were problems backing up" +#. Inserted at the end of the statusbar message concerning the amount of freespace +#. Used to differentiate between two different file systems +#. e.g. Free space: 21.3GB (photos); 14.7GB (videos). +#: rapid/rapid.py:2691 +msgid "." msgstr "" -"%(filetype)s загружено, но возникли проблемы с его резервным копированием" -#: rapid/rapid.py:3982 +#. Freespace available on the filesystem for downloading to +#. Displayed in status bar message on main window +#. e.g. 14.7GB available +#: rapid/rapid.py:2697 #, python-format -msgid "%(filetype)s was neither downloaded nor backed up" -msgstr "%(filetype)s не был ни скачан, ни резервно скопирован" - -#: rapid/rapid.py:3984 -#, python-format -msgid "%(filetype)s is ready to be downloaded" -msgstr "%(filetype)s готово к загрузке" - -#: rapid/rapid.py:3986 -#, python-format -msgid "%(filetype)s is about to be downloaded" -msgstr "%(filetype)s ожидает загрузки" - -#: rapid/rapid.py:3988 -#, python-format -msgid "%(filetype)s will be downloaded with warnings" -msgstr "%(filetype)s будет загружено с предупреждениями" - -#: rapid/rapid.py:3990 -#, python-format -msgid "%(filetype)s cannot be downloaded" -msgstr "%(filetype)s не может быть загружено" - -#: rapid/rapid.py:4662 -msgid "Enter a new Job Code and press Enter, or select an existing Job Code" -msgstr "Введите новую метку и нажмите Enter или выберите существующую метку" - -#: rapid/rapid.py:5034 -#, python-format -msgid "%(free)s available" -msgstr "%(free)s доступно" +msgid "%(free)s free" +msgstr "" #. user manually specified backup location -#: rapid/rapid.py:5040 +#: rapid/rapid.py:2703 #, python-format msgid "Backing up to %(path)s" msgstr "Резервное копирование в %(path)s" -#: rapid/rapid.py:5045 +#: rapid/rapid.py:2708 #, python-format msgid "%(freespace)s. %(backuppaths)s." msgstr "%(freespace)s. %(backuppaths)s." -#: rapid/rapid.py:5054 -#, python-format -msgid "" -"Sorry, this device location does not exist:\n" -"%(path)s\n" -"\n" -"Please resolve the problem, or modify your preferences." -msgstr "" -"Извините, указанное расположение на носителя не существует:\n" -"%(path)s\n" -"Пожалуйста, исправьте ошибку или измените настройки" +#: rapid/rapid.py:2737 +msgid "Program preferences are invalid" +msgstr "Настройки программы не корректны" -#: rapid/rapid.py:5058 -msgid "Problem with Device Location Folder" -msgstr "Проблема с расположением носителя" +#: rapid/rapid.py:2842 rapid/rpdfile.py:247 +msgid "Photo" +msgstr "Фото" -#: rapid/rapid.py:5067 +#: rapid/rapid.py:2844 rapid/rpdfile.py:267 msgid "Video" msgstr "Видео" -#: rapid/rapid.py:5074 -#, python-format -msgid "The %(file_type)s Download Folder does not exist.\n" -msgstr "Каталог для загрузки %(file_type)s не существует.\n" - -#: rapid/rapid.py:5083 -#, python-format -msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" -msgstr "" -"Каталог для загрузки %(file_type)s существует, но недоступен для записи.\n" - -#: rapid/rapid.py:5088 -msgid "" -"Sorry, problems were encountered with your download folders. Please fix the " -"problems or modify the preferences.\n" -"\n" -msgstr "" -"Извините, были обнаружены проблемы с каталогами для загрузки. Пожалуйста, " -"исправьте их или измените настройки.\n" -"\n" - -#: rapid/rapid.py:5091 -msgid "Problem with Download Folder" -msgstr "Проблема с каталогом для загрузки" - -#: rapid/rapid.py:5093 -msgid "Problem with Download Folders" -msgstr "Проблема с каталогами для загрузки" - -#: rapid/rapid.py:5106 -msgid "Some preferences will be reset." -msgstr "Некоторые настройки будут сброшены." - -#: rapid/rapid.py:5139 -msgid "Displaying warning about downloading directly from camera" -msgstr "Отображает предупреждения о прямой загрузке с камеры" - -#: rapid/rapid.py:5149 -#, python-format -msgid "Prompting whether to use %s" -msgstr "Спрашивать, использовать ли %s" - -#: rapid/rapid.py:5176 -msgid "Prompting for Job Code" -msgstr "Предлагать использовать метку" - -#: rapid/rapid.py:5180 -msgid "Already prompting for Job Code, do not prompt again" -msgstr "Уже предложено использовать метку, больше не спрашивать" - -#: rapid/rapid.py:5197 -msgid "Starting downloads" -msgstr "Начинаются загрузки" - -#. autostart is true -#: rapid/rapid.py:5201 -msgid "Starting downloads that have been waiting for a Job Code" -msgstr "Начинаются загрузки, которые ожидали ввода метки" - -#: rapid/rapid.py:5248 -#, python-format -msgid "Creating photo download folder %(folder)s" -msgstr "Создание каталога для загрузки фото %(folder)s" - -#: rapid/rapid.py:5253 -#, python-format -msgid "Failed to create default photo download folder %(folder)s" -msgstr "Не удалось создать каталог для загрузки фото %(folder)s" - -#: rapid/rapid.py:5257 -#, python-format -msgid "Creating video download folder %(folder)s" -msgstr "Создание каталога для загрузки видео %(folder)s" - -#: rapid/rapid.py:5262 -#, python-format -msgid "Failed to create default video download folder %(folder)s" -msgstr "Не удалось создать каталог для загрузки видео %(folder)s" - -#: rapid/rapid.py:5287 -msgid "" -"A newer version of this program was previously run on this computer.\n" -"\n" -msgstr "" -"На этом компьютере ранее запускалась более новая версия программы.\n" -"\n" - -#: rapid/rapid.py:5289 -msgid "" -"Program preferences appear to be valid, but please check them to ensure " -"correct operation." -msgstr "" -"Настройки программы выглядят верными, но проверьте их, чтобы увериться в " -"правильной работе." - -#: rapid/rapid.py:5291 -msgid "Sorry, some preferences are invalid and will be reset." -msgstr "Извините, некоторые настройки неверны и будут сброшены." - -#: rapid/rapid.py:5292 -msgid "Warning:" -msgstr "Предупреждение:" - -#: rapid/rapid.py:5297 -msgid "" -"This version of the program is newer than the previously run version. " -"Checking preferences." -msgstr "" -"Эта версия программы новее, чем запущенная ранее. Проверьте настройки." - -#: rapid/rapid.py:5304 -msgid "Preferences were modified." -msgstr "Настройки были изменены" - -#: rapid/rapid.py:5305 -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:5309 -msgid "No preferences needed to be changed." -msgstr "Настройки не требуют изменения." - -#: rapid/rapid.py:5311 -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:5321 -msgid "Problem using pynotify." -msgstr "Проблема при использовании pynotify." - -#: rapid/rapid.py:5337 -msgid "Failed to receive pynotify server capabilities." -msgstr "Не удалось получить возможности сервера pynotify." - -#: rapid/rapid.py:5348 -msgid "" -"Warning: desktop environment notification server is incorrectly configured." -msgstr "" -"Внимание: сервер уведомлений вашего рабочего окружения не настроен " -"надлежащим образом." - -#: rapid/rapid.py:5396 -msgid "and" -msgstr "и" - -#: rapid/rapid.py:5401 -msgid "Using backup devices" -msgstr "Использование носителя для резервного копирования" - -#: rapid/rapid.py:5403 -msgid "Using backup device" -msgstr "Использование носителя для резервного копирования" - -#: rapid/rapid.py:5405 -msgid "No backup devices detected" -msgstr "Не обнаружено носителей для создания резервных копий" - -#: rapid/rapid.py:5455 rapid/rapid.py:5617 +#: rapid/rapid.py:2853 #, python-format -msgid "Device %(device)s (%(path)s) ignored" -msgstr "Носитель %(device)s (%(path)s) проигнорирован" +msgid "%(file_type)s download folder does not exist" +msgstr "%(file_type)s каталог для закачки не существует" -#: rapid/rapid.py:5576 +#: rapid/rapid.py:2855 rapid/rapid.py:2869 rapid/rapid.py:2882 #, python-format -msgid "Detected %(device)s with path %(path)s" -msgstr "Обнаружено %(device)s с путём %(path)s" - -#: rapid/rapid.py:5580 -msgid "Automatically start download is true" -msgstr "Автоматически начинать загрузку - да" - -#: rapid/rapid.py:5582 -msgid "Automatically start download is false" -msgstr "Автоматически начинать загрузку - нет" - -#: rapid/rapid.py:5635 -msgid "Using manually specified path" -msgstr "Использовать указанный вручную путь" +msgid "Folder: %s" +msgstr "Каталог: %s" -#. the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? -#: rapid/rapid.py:5703 +#: rapid/rapid.py:2867 #, python-format -msgid "Warning: backup device %(device)s is currently being downloaded from" +msgid "%(file_type)s download folder is invalid" msgstr "" -"Внимание: с устройства для резервного копирования %(device)s в данный момент " -"идет загрузка" - -#: rapid/rapid.py:5719 -msgid "D_ownload Selected" -msgstr "З_агрузить отмеченное" - -#: rapid/rapid.py:5822 rapid/rapid.py:5873 -msgid "All downloads complete" -msgstr "Все загрузки завершены" -#: rapid/rapid.py:5837 -msgid "MB/s" -msgstr "МБ/с" - -#: rapid/rapid.py:5847 -msgid "About 1 second remaining" -msgstr "Осталась примерно 1 секунда" - -#: rapid/rapid.py:5849 -#, python-format -msgid "About %i seconds remaining" -msgstr "Осталось %i секунд" - -#: rapid/rapid.py:5851 -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:5856 +#: rapid/rapid.py:2880 #, python-format -msgid "About %(minutes)i:%(seconds)02i minutes remaining" -msgstr "Осталось примерно %(minutes)i:%(seconds)02i" +msgid "%(file_type)s download folder is not writable" +msgstr "%(file_type)s в каталог для закачки невозможно записать" -#: rapid/rapid.py:5876 rapid/rapid.py:5882 rapid/rapid.py:5888 -#: rapid/rapid.py:5894 rapid/rapid.py:5899 rapid/rapid.py:5903 -#, python-format -msgid "%(number)s %(numberdownloaded)s" -msgstr "%(number)s %(numberdownloaded)s" - -#: rapid/rapid.py:5878 rapid/rapid.py:5890 -#, python-format -msgid "%(filetype)s downloaded" -msgstr "%(filetype)s загружено" - -#: rapid/rapid.py:5884 rapid/rapid.py:5896 -#, python-format -msgid "%(filetype)s failed to download" -msgstr "%(filetype)s не удалось загрузить" - -#: rapid/rapid.py:6070 -msgid "_Resume" -msgstr "_Продолжить" - -#: rapid/rapid.py:6073 -msgid "_Download All" -msgstr "_Загрузить всё" - -#. This text will be displayed to the user on the Download / Pause button. -#: rapid/rapid.py:6082 -msgid "_Pause" -msgstr "_Пауза" - -#: rapid/rapid.py:6194 -msgid "Download device settings preferences were changed." -msgstr "Настройки устройства загрузки были изменены." - -#: rapid/rapid.py:6206 -msgid "Backup preferences were changed." -msgstr "Настройки резвервного копирования были изменены." - -#: rapid/rapid.py:6212 -msgid "Subfolder and filename preferences were changed." -msgstr "Настройки каталогов и названий файлов были изменены." - -#: rapid/rapid.py:6223 -msgid "Download folder preferences were changed." -msgstr "Настройки каталога для загрузки были изменены." - -#: rapid/rapid.py:6422 -msgid "Goodbye" -msgstr "До свидания" +#: rapid/rapid.py:2958 +msgid "Thumbnails" +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:6433 +#: rapid/rapid.py:3005 #, python-format msgid "" "display program information on the command line as the program runs " @@ -1083,582 +291,1209 @@ msgstr "" "отобразить информацию о программе в командной строке при запуске программы " "(по умолчанию: %default)" -#: rapid/rapid.py:6434 +#: rapid/rapid.py:3006 msgid "display debugging information when run from the command line" msgstr "отображать отладочную информацию при запуске из командной строки" -#: rapid/rapid.py:6435 +#: rapid/rapid.py:3007 msgid "only output errors to the command line" msgstr "выводить в командную строку только ошибки" #. image file extensions are recognized RAW files plus TIFF and JPG -#: rapid/rapid.py:6437 +#: rapid/rapid.py:3009 msgid "list photo and video file extensions the program recognizes and exit" msgstr "" "вывести расширения фото- и видеофайлов, которые распознает программа, и выйти" -#: rapid/rapid.py:6438 +#: rapid/rapid.py:3010 msgid "reset all program settings and preferences and exit" msgstr "сбросить все настройки и выйти" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:3023 msgid "Photos:" msgstr "Фото:" -#: rapid/rapid.py:6452 +#: rapid/rapid.py:3023 msgid "Videos:" msgstr "Видео:" -#: rapid/rapid.py:6457 +#: rapid/rapid.py:3028 #, python-format msgid "and %s" msgstr "и %s" -#: rapid/rapid.py:6465 +#: rapid/rapid.py:3036 msgid "All settings and preferences have been reset" msgstr "Все установки и настройки были сброшены" -#. Which volume management code is being used (GIO or GnomeVFS) -#: rapid/rapid.py:6469 rapid/rapid.py:6470 rapid/rapid.py:6472 -#: rapid/rapid.py:6477 rapid/rapid.py:6481 -msgid "Using" -msgstr "Использование" - -#: rapid/rapid.py:6474 -msgid "\n" -msgstr "\n" +#: rapid/rapid.py:3045 +msgid "" +"Video downloading functionality disabled.\n" +"To download videos, please install the hachoir metadata and kaa metadata " +"packages for python." +msgstr "" +"Загрузка видеороликов отключена.\n" +"Для загрузки видеороликов, пожалуйста, установите пакеты метаданных hachoir " +"и kaa." -#. this application is already running -#: rapid/rapid.py:6498 +#: rapid/copyfiles.py:142 rapid/subfolderfile.py:209 +#: rapid/subfolderfile.py:332 rapid/subfolderfile.py:350 #, python-format -msgid "%s is already running" -msgstr "%s уже запущено" +msgid "" +"%(problem)s\n" +"File: %(file)s" +msgstr "" +"%(problem)s\n" +"Файл: %(file)s" + +#: rapid/device.py:79 +msgid "Device Detected" +msgstr "Обнаружен носитель" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:88 +msgid "" +"Should this device or partition be used to download photos or videos from?" +msgstr "Следует ли загрузить фото или видео с этого носителя или раздела?" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt +#: rapid/device.py:107 +msgid "_Remember this choice" +msgstr "_Запомнить мой выбор" + +#: rapid/downloadtracker.py:217 +msgid "MB/s" +msgstr "МБ/с" -#: rapid/renamesubfolderprefs.py:192 +#: rapid/generatenameconfig.py:143 msgid "Date time" msgstr "Дата и время" -#: rapid/renamesubfolderprefs.py:193 +#: rapid/generatenameconfig.py:144 msgid "Text" msgstr "Текст" -#: rapid/renamesubfolderprefs.py:195 +#: rapid/generatenameconfig.py:145 +msgid "Filename" +msgstr "Имя файла" + +#: rapid/generatenameconfig.py:146 msgid "Metadata" msgstr "Метаданные" -#: rapid/renamesubfolderprefs.py:196 +#: rapid/generatenameconfig.py:147 msgid "Sequences" msgstr "Последовательности" -#: rapid/renamesubfolderprefs.py:199 +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/generatenameconfig.py:149 rapid/preferencesdialog.py:549 +msgid "Job code" +msgstr "Метка" + +#: rapid/generatenameconfig.py:150 msgid "Image date" msgstr "Дата фотографии" -#: rapid/renamesubfolderprefs.py:200 +#: rapid/generatenameconfig.py:151 msgid "Video date" msgstr "Дата видео" -#: rapid/renamesubfolderprefs.py:201 +#: rapid/generatenameconfig.py:152 msgid "Today" msgstr "Сегодня" -#: rapid/renamesubfolderprefs.py:202 +#: rapid/generatenameconfig.py:153 msgid "Yesterday" msgstr "Вчера" #. Translators: Download time is the time and date that the download started (when the user clicked the Download button) -#: rapid/renamesubfolderprefs.py:204 +#: rapid/generatenameconfig.py:155 msgid "Download time" msgstr "Время начала загрузки" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:206 +#: rapid/generatenameconfig.py:157 msgid "Name + extension" msgstr "Имя + расширение" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:208 +#: rapid/generatenameconfig.py:159 msgid "Name" msgstr "Имя" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:210 +#: rapid/generatenameconfig.py:161 msgid "Extension" msgstr "Расширение" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:212 +#: rapid/generatenameconfig.py:163 msgid "Image number" msgstr "Номер фотографии" -#: rapid/renamesubfolderprefs.py:213 +#: rapid/generatenameconfig.py:164 msgid "Video number" msgstr "Номер видео" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:215 +#: rapid/generatenameconfig.py:166 msgid "Aperture" msgstr "Диафрагма" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:217 +#: rapid/generatenameconfig.py:168 msgid "ISO" msgstr "ISO" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:219 +#: rapid/generatenameconfig.py:170 msgid "Exposure time" msgstr "Выдержка" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:221 +#: rapid/generatenameconfig.py:172 msgid "Focal length" msgstr "Фокусное расстояние" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:223 +#: rapid/generatenameconfig.py:174 msgid "Camera make" msgstr "Производитель камеры" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:225 +#: rapid/generatenameconfig.py:176 msgid "Camera model" msgstr "Модель камеры" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:227 +#: rapid/generatenameconfig.py:178 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:229 +#: rapid/generatenameconfig.py:180 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:231 +#: rapid/generatenameconfig.py:182 msgid "Serial number" msgstr "Серийный номер" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:233 +#: rapid/generatenameconfig.py:184 msgid "Shutter count" msgstr "Счётчик кадров" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata -#: rapid/renamesubfolderprefs.py:235 +#: rapid/generatenameconfig.py:186 msgid "Owner name" msgstr "Имя владельца" -#: rapid/renamesubfolderprefs.py:236 +#: rapid/generatenameconfig.py:187 msgid "Codec" msgstr "Кодек" -#: rapid/renamesubfolderprefs.py:237 +#: rapid/generatenameconfig.py:188 msgid "Width" msgstr "Ширина" -#: rapid/renamesubfolderprefs.py:238 +#: rapid/generatenameconfig.py:189 msgid "Height" msgstr "Высота" -#: rapid/renamesubfolderprefs.py:239 +#: rapid/generatenameconfig.py:190 msgid "Length" msgstr "Длительность" -#: rapid/renamesubfolderprefs.py:240 +#: rapid/generatenameconfig.py:191 msgid "Frames Per Second" msgstr "Кадров в секунду" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:242 +#: rapid/generatenameconfig.py:193 msgid "Downloads today" msgstr "Скачиваний сегодня" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:244 +#: rapid/generatenameconfig.py:195 msgid "Session number" msgstr "Номер в текущей сессии" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:246 +#: rapid/generatenameconfig.py:197 msgid "Subfolder number" msgstr "Номер подкаталога" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers -#: rapid/renamesubfolderprefs.py:248 +#: rapid/generatenameconfig.py:199 msgid "Stored number" msgstr "Сквозная нумерация" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters -#: rapid/renamesubfolderprefs.py:250 +#: rapid/generatenameconfig.py:201 msgid "Sequence letter" msgstr "Последовательность символов" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:252 +#: rapid/generatenameconfig.py:203 msgid "All digits" msgstr "Все цифры" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:254 +#: rapid/generatenameconfig.py:205 msgid "Last digit" msgstr "Последняя цифра" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename -#: rapid/renamesubfolderprefs.py:256 +#: rapid/generatenameconfig.py:207 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:258 +#: rapid/generatenameconfig.py:209 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:260 +#: rapid/generatenameconfig.py:211 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:262 +#: rapid/generatenameconfig.py:213 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:264 +#: rapid/generatenameconfig.py:215 msgid "UPPERCASE" msgstr "ВЕРХНИЙ РЕГИСТР" #. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization -#: rapid/renamesubfolderprefs.py:266 +#: rapid/generatenameconfig.py:217 msgid "lowercase" msgstr "нижний регистр" -#: rapid/renamesubfolderprefs.py:267 +#: rapid/generatenameconfig.py:218 msgid "One digit" msgstr "Одна цифра" -#: rapid/renamesubfolderprefs.py:268 +#: rapid/generatenameconfig.py:219 msgid "Two digits" msgstr "Две цифры" -#: rapid/renamesubfolderprefs.py:269 +#: rapid/generatenameconfig.py:220 msgid "Three digits" msgstr "Три цифры" -#: rapid/renamesubfolderprefs.py:270 +#: rapid/generatenameconfig.py:221 msgid "Four digits" msgstr "Четыре цифры" -#: rapid/renamesubfolderprefs.py:271 +#: rapid/generatenameconfig.py:222 msgid "Five digits" msgstr "Пять цифр" -#: rapid/renamesubfolderprefs.py:272 +#: rapid/generatenameconfig.py:223 msgid "Six digits" msgstr "Шесть цифр" -#: rapid/renamesubfolderprefs.py:273 +#: rapid/generatenameconfig.py:224 msgid "Seven digits" msgstr "семь цифр" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:275 +#: rapid/generatenameconfig.py:226 msgid "Subseconds" msgstr "Доли секунды" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:277 +#: rapid/generatenameconfig.py:228 msgid "YYYYMMDD" msgstr "ГГГГММДД" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:279 +#: rapid/generatenameconfig.py:230 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:281 +#: rapid/generatenameconfig.py:232 msgid "YYMMDD" msgstr "ГГММДД" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:283 +#: rapid/generatenameconfig.py:234 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:285 +#: rapid/generatenameconfig.py:236 msgid "MMDDYYYY" msgstr "ММДДГГГГ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:287 +#: rapid/generatenameconfig.py:238 msgid "MMDDYY" msgstr "ММДДГГ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:289 +#: rapid/generatenameconfig.py:240 msgid "MMDD" msgstr "ММДД" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:291 +#: rapid/generatenameconfig.py:242 msgid "DDMMYYYY" msgstr "ДДММГГГГ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:293 +#: rapid/generatenameconfig.py:244 msgid "DDMMYY" msgstr "ДДММГГ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:295 +#: rapid/generatenameconfig.py:246 msgid "YYYY" msgstr "ГГГГ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:297 +#: rapid/generatenameconfig.py:248 msgid "YY" msgstr "ГГ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:299 +#: rapid/generatenameconfig.py:250 msgid "MM" msgstr "ММ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:301 +#: rapid/generatenameconfig.py:252 msgid "DD" msgstr "ДД" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:303 +#: rapid/generatenameconfig.py:254 msgid "HHMMSS" msgstr "ЧЧММСС" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:305 +#: rapid/generatenameconfig.py:256 msgid "HHMM" msgstr "ЧЧММ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:307 +#: rapid/generatenameconfig.py:258 msgid "HH-MM-SS" msgstr "ЧЧ-ММ-СС" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:309 +#: rapid/generatenameconfig.py:260 msgid "HH-MM" msgstr "ЧЧ-ММ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:311 +#: rapid/generatenameconfig.py:262 msgid "HH" msgstr "ЧЧ" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:313 +#: rapid/generatenameconfig.py:264 msgid "MM (minutes)" msgstr "ММ (мин.)" #. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime -#: rapid/renamesubfolderprefs.py:315 +#: rapid/generatenameconfig.py:266 msgid "SS" msgstr "СС" -#: rapid/renamesubfolderprefs.py:800 +#: rapid/preferencesdialog.py:370 +#, python-format +msgid "Subfolder preferences should not start with a %s" +msgstr "Настройки подкаталога не должны начинаться с %s" + +#: rapid/preferencesdialog.py:372 +#, python-format +msgid "Subfolder preferences should not end with a %s" +msgstr "Настройки подкаталога не должны заканчиваться с %s" + +#: rapid/preferencesdialog.py:376 +#, python-format +msgid "Subfolder preferences should not contain two %s one after the other" +msgstr "Настройки подкаталога не должны содержать две %s одну за другой" + +#: rapid/preferencesdialog.py:389 rapid/preferencesdialog.py:672 +msgid "Remove all Job Codes?" +msgstr "Удалить все метки?" + +#: rapid/preferencesdialog.py:406 rapid/preferencesdialog.py:689 +msgid "Should all Job Codes be removed?" +msgstr "Вы действительно хотите удалить все метки?" + +#: rapid/preferencesdialog.py:436 +msgid "Error in Photo Rename preferences" +msgstr "Ошибка в параметрах Переименования фото" + +#: rapid/preferencesdialog.py:617 +msgid "Error in Video Rename preferences" +msgstr "Ошибка в параметрах Переименования видео" + +#: rapid/preferencesdialog.py:638 +msgid "Error in Photo Download Subfolders preferences" +msgstr "Ошибка в параметрах Подкаталогов для загрузки фото" + +#: rapid/preferencesdialog.py:655 +msgid "Error in Video Download Subfolders preferences" +msgstr "Ошибка в параметрах Подкаталогов для загрузки видео" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:714 +msgid "Enter a Job Code" +msgstr "Введите метку" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:731 +msgid "Enter a new Job Code, or select a previous one" +msgstr "Введите новую метку или выберите одну из существующих" + +#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode +#: rapid/preferencesdialog.py:734 +msgid "Enter a new Job Code" +msgstr "Введите новую метку" + +#: rapid/preferencesdialog.py:739 +msgid "Job Code:" +msgstr "Метка:" + +#: rapid/preferencesdialog.py:915 +msgid "Job Code" +msgstr "Метка" + +#: rapid/preferencesdialog.py:997 +msgid "Select a folder to download photos to" +msgstr "Выберите каталог для загрузки фото" + +#: rapid/preferencesdialog.py:1015 +msgid "Select a folder to download videos to" +msgstr "Выберите каталог для загрузки видео" + +#: rapid/preferencesdialog.py:1106 +#, python-format +msgid "Select a folder containing %(file_types)s" +msgstr "Выберите каталог, содержащий %(file_types)s" + +#: rapid/preferencesdialog.py:1128 +#, python-format +msgid "Select a folder in which to backup %(file_types)s" +msgstr "" +"Выберите каталог в котором будут храниться резервные копии %(file_types)s" + +#. 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/preferencesdialog.py:1212 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate the " +"name. Please use other renaming options.</i>" +msgstr "" +"<i><b>Внимание:</b> Недостаточно метаданных для создания имен файлов. " +"Пожалуйста, используйте другие варианты переименования.</i>" + +#: rapid/preferencesdialog.py:1263 +msgid "" +"<i><b>Warning:</b> There is insufficient metadata to fully generate " +"subfolders. Please use other subfolder naming options.</i>" +msgstr "" +"<i><b>Warning:</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/preferencesdialog.py:1266 +#, python-format +msgid "<i>Example: %s</i>" +msgstr "<i>Пример: %s</i>" + +#. Preferences list is now empty +#: rapid/preferencesdialog.py:1356 +#, python-format +msgid "" +"The %(filetype)s subfolder preferences entered are invalid and cannot be " +"used.\n" +"They will be reset to their default values." +msgstr "" +"Введённые настройки подкаталога для %(filetype)s неверны и не могут быть " +"использованы.\n" +"Они сброшены до значений по умолчанию." + +#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. +#: rapid/preferencesdialog.py:1642 +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/preferencesdialog.py:1644 +msgid "externaldrive2" +msgstr "внешнийдиск2" + +#: rapid/prefsrapid.py:122 +msgid "New York" +msgstr "Нью-Йорк" + +#: rapid/prefsrapid.py:123 +msgid "Manila" +msgstr "Манила" + +#: rapid/prefsrapid.py:123 +msgid "Prague" +msgstr "Прага" + +#: rapid/prefsrapid.py:123 +msgid "Helsinki" +msgstr "Хельсинки" + +#: rapid/prefsrapid.py:123 +msgid "Wellington" +msgstr "Веллингтон" + +#: rapid/prefsrapid.py:124 +msgid "Tehran" +msgstr "Тегеран" + +#: rapid/prefsrapid.py:124 +msgid "Kampala" +msgstr "Кампала" + +#: rapid/prefsrapid.py:124 +msgid "Paris" +msgstr "Париж" + +#: rapid/prefsrapid.py:124 +msgid "Berlin" +msgstr "Берлин" + +#: rapid/prefsrapid.py:124 +msgid "Sydney" +msgstr "Сидней" + +#: rapid/prefsrapid.py:125 +msgid "Budapest" +msgstr "Будапешт" + +#: rapid/prefsrapid.py:125 +msgid "Rome" +msgstr "Рим" + +#: rapid/prefsrapid.py:125 +msgid "Moscow" +msgstr "Москва" + +#: rapid/prefsrapid.py:125 +msgid "Delhi" +msgstr "Дели" + +#: rapid/prefsrapid.py:125 +msgid "Warsaw" +msgstr "Варшава" + +#: rapid/prefsrapid.py:126 +msgid "Jakarta" +msgstr "Джакарта" + +#: rapid/prefsrapid.py:126 +msgid "Madrid" +msgstr "Мадрид" + +#: rapid/prefsrapid.py:126 +msgid "Stockholm" +msgstr "Стокгольм" + +#. components +#: rapid/problemnotification.py:26 rapid/subfolderfile.py:343 +msgid "subfolder" +msgstr "подкаталог" + +#: rapid/problemnotification.py:27 rapid/subfolderfile.py:341 +msgid "filename" +msgstr "имя файла" + +#: rapid/problemnotification.py:80 +#, python-format +msgid "Date time value %s appears invalid." +msgstr "" + +#: rapid/problemnotification.py:81 +msgid "Filename does not have an extension." +msgstr "Название файла не содержит расширения." + +#. a number component is something like the 8346 in IMG_8346.JPG +#: rapid/problemnotification.py:83 +msgid "Filename does not have a number component." +msgstr "" + +#: rapid/problemnotification.py:84 +#, python-format +msgid "Error generating component %s." +msgstr "Ошибка создания компонента %s." + +#. a generic problem +#: rapid/problemnotification.py:86 +#, python-format +msgid "%(filetype)s metadata cannot be read" +msgstr "%(filetype)s метаданные невозможно прочесть" + +#: rapid/problemnotification.py:88 +#, python-format +msgid "%(filetype)s %(area)s could not be generated" +msgstr "%(filetype)s %(area)s не удалось создать" + +#: rapid/problemnotification.py:90 rapid/problemnotification.py:91 +#, python-format +msgid "An error occurred when copying the %(filetype)s" +msgstr "Произошла ошибка при копировании %(filetype)s" + +#: rapid/problemnotification.py:93 rapid/problemnotification.py:94 +#, python-format +msgid "%(filetype)s already exists" +msgstr "%(filetype)s уже существует" + +#: rapid/problemnotification.py:97 #, python-format msgid "" -"Preference key '%(key)s' is invalid.\n" -"Expected one of %(value)s" +"%(filetype)s could not be backed up because no suitable backup locations " +"were found." msgstr "" -"Неверен ключ настроек '%(key)s'.\n" -"Ожидался один из %(value)s" +"%(filetype)s не может быть сохранен в резервной копии, так как не найдено " +"хранилище резервных копий." -#: rapid/renamesubfolderprefs.py:807 +#: rapid/problemnotification.py:102 #, python-format -msgid "Preference value '%(value)s' is invalid" -msgstr "Неверное значение настроек '%(value)s'" +msgid "" +"%(image1)s was taken at on %(image1_date)s at %(image1_time)s, and " +"%(image2)s on %(image2_date)s at %(image2_time)s." +msgstr "" -#: rapid/renamesubfolderprefs.py:811 -msgid "These preferences are not well formed:" -msgstr "Эти настройки не очень хорошо подобраны:" +#: rapid/problemnotification.py:103 +#, python-format +msgid "%(filetype)s was already downloaded" +msgstr "%(filetype)s уже был загружен" -#: rapid/renamesubfolderprefs.py:1524 +#: rapid/problemnotification.py:107 #, python-format -msgid "Subfolder preferences should not start with a %s" -msgstr "Настройки подкаталога не должны начинаться с %s" +msgid "" +"The existing %(filetype)s was last modified on %(date)s at %(time)s. Unique " +"identifier '%(identifier)s' added." +msgstr "" -#: rapid/renamesubfolderprefs.py:1526 +#: rapid/problemnotification.py:108 #, python-format -msgid "Subfolder preferences should not end with a %s" -msgstr "Настройки подкаталога не должны заканчиваться с %s" +msgid "The existing %(filetype)s was last modified on %(date)s at %(time)s." +msgstr "" -#: rapid/renamesubfolderprefs.py:1530 +#: rapid/problemnotification.py:109 #, python-format -msgid "Subfolder preferences should not contain two %s one after the other" -msgstr "Настройки подкаталога не должны содержать две %s одну за другой" +msgid "There is no data with which to name the %(filetype)s." +msgstr "" + +#: rapid/problemnotification.py:111 +#, python-format +msgid "Error: %(errorno)s %(strerror)s" +msgstr "" + +#: rapid/problemnotification.py:201 +msgid "The metadata might be corrupt." +msgstr "Метаданные могут быть повреждены." + +#: rapid/problemnotification.py:204 +msgid "" +"The filename, extension and Exif information indicate it has already been " +"downloaded." +msgstr "" + +#: rapid/problemnotification.py:223 +#, python-format +msgid " It was backed up to %(volume)s" +msgstr " Сделана резервная копия на %(volume)s" + +#: rapid/problemnotification.py:225 +msgid " It was backed up to these devices: " +msgstr " Сделана резервная копия на: " + +#: rapid/problemnotification.py:227 rapid/problemnotification.py:288 +#: rapid/problemnotification.py:300 +#, python-format +msgid "%s, " +msgstr "%s, " + +#: rapid/problemnotification.py:228 rapid/problemnotification.py:289 +#: rapid/problemnotification.py:301 +#, python-format +msgid "%(volumes)s and %(final_volume)s." +msgstr "%(volumes)s и %(final_volume)s." + +#: rapid/problemnotification.py:240 +#, python-format +msgid "" +"Photos detected with the same filenames, but taken at different times: " +"%(details)s" +msgstr "" +"Обнаружены фотографии с одинаковыми названиями, но сделанные в разное время: " +"%(details)s" + +#: rapid/problemnotification.py:257 +#, python-format +msgid "An error occurred when backing up on %(volume)s: %(inst)s." +msgstr "" +"Произошла ошибка при создании резервной копии на %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:259 +#, python-format +msgid "An error occurred when backing up on %(volume)s." +msgstr "Произошла ошибка при создании резервной копии на %(volume)s." + +#: rapid/problemnotification.py:261 +msgid "Errors occurred when backing up on the following backup devices: " +msgstr "" +"Произошли ошибки при создании резервной копии на следующих носителях: " + +#: rapid/problemnotification.py:265 rapid/problemnotification.py:313 +#, python-format +msgid "%(volume)s (%(inst)s), " +msgstr "%(volume)s (%(inst)s), " + +#: rapid/problemnotification.py:267 +#, python-format +msgid "%(volume)s, " +msgstr "" + +#: rapid/problemnotification.py:271 rapid/problemnotification.py:315 +#, python-format +msgid "%(volumes)s and %(volume)s (%(inst)s)." +msgstr "" + +#: rapid/problemnotification.py:276 +#, python-format +msgid "%(volumes)s and %(volume)s." +msgstr "%(volumes)s и %(volume)s." + +#: rapid/problemnotification.py:284 +#, python-format +msgid "Backup already exists on %(volume)s." +msgstr "Уже существует резервная копия на %(volume)s." + +#: rapid/problemnotification.py:286 +msgid "Backups already exist in these locations: " +msgstr "Уже существует резервная копия на: " + +#: rapid/problemnotification.py:296 +#, python-format +msgid "Backup overwritten on %(volume)s." +msgstr "" + +#: rapid/problemnotification.py:298 +msgid "Backups overwritten on these devices: " +msgstr "" + +#: rapid/problemnotification.py:309 +#, python-format +msgid "An error occurred when creating directories on %(volume)s: %(inst)s." +msgstr "Произошла ошибка при создании каталогов на %(volume)s: %(inst)s." + +#: rapid/problemnotification.py:311 +msgid "" +"Errors occurred when creating directories on the following backup devices: " +msgstr "Произошла ошибка при создании каталогов на следующих устройствах: " + +#: rapid/problemnotification.py:322 +#, python-format +msgid "%(previousproblem)s Additionally, %(newproblem)s" +msgstr "" -#: rapid/glade3/rapid.glade.h:1 +#: rapid/problemnotification.py:330 +#, python-format +msgid " Furthermore, there were %(problems)s." +msgstr "" + +#: rapid/problemnotification.py:332 +#, python-format +msgid " Furthermore, there was a %(problem)s." +msgstr "" + +#: rapid/problemnotification.py:341 +#, python-format +msgid "The %(type)s metadata is missing." +msgstr "" + +#: rapid/problemnotification.py:343 +msgid "The following metadata is missing: " +msgstr "Эти метаданные пропущены: " + +#: rapid/problemnotification.py:346 +#, python-format +msgid "%(missing_metadata_elements)s and %(final_missing_metadata_element)s." +msgstr "" + +#: rapid/problemnotification.py:363 +msgid "Problems in subfolder and filename generation" +msgstr "" + +#: rapid/problemnotification.py:365 +msgid "Problem in subfolder and filename generation" +msgstr "" + +#: rapid/problemnotification.py:368 +#, python-format +msgid "Problems in %s generation" +msgstr "" + +#: rapid/problemnotification.py:370 +#, python-format +msgid "Problem in %s generation" +msgstr "" + +#: rapid/problemnotification.py:379 +#, python-format +msgid "%(filetype)s already exists, but it was backed up" +msgstr "" + +#: rapid/problemnotification.py:381 +#, python-format +msgid "An error occurred when copying the %(filetype)s, but it was backed up" +msgstr "" + +#: rapid/problemnotification.py:401 +msgid "Multiple problems were encountered" +msgstr "Обнаружены многочисленные проблемы" + +#: rapid/problemnotification.py:403 rapid/subfolderfile.py:228 +msgid "Photos detected with the same filenames, but taken at different times" +msgstr "" +"Обнаружены фотографии с одинаковыми названиями, но сделанные в разное время" + +#: rapid/problemnotification.py:409 +msgid "there were errors backing up" +msgstr "" + +#: rapid/problemnotification.py:410 +msgid "There were errors backing up" +msgstr "" + +#: rapid/problemnotification.py:412 +msgid "there was an error backing up" +msgstr "" + +#: rapid/problemnotification.py:413 +msgid "There was an error backing up" +msgstr "" + +#. e.g. +#: rapid/problemnotification.py:416 +#, python-format +msgid "%(previousproblem)s, and %(backinguperror)s" +msgstr "" + +#: rapid/rpdfile.py:136 +#, python-format +msgid "%(number)s %(filetypes)s" +msgstr "%(number)s %(filetypes)s" + +#: rapid/subfolderfile.py:79 +#, python-format +msgid "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" +msgstr "%(hour)s:%(minute)s:%(second)s:%(subsecond)s" + +#: rapid/subfolderfile.py:194 +#, python-format +msgid "" +"Source: %(source)s\n" +"Destination: %(destination)s" +msgstr "" +"Источник: %(source)s\n" +"Назначение: %(destination)s" + +#: rapid/subfolderfile.py:297 +msgid "Photo has already been downloaded" +msgstr "Фото уже загружено" + +#: rapid/subfolderfile.py:298 +#, python-format +msgid "Source: %(source)s" +msgstr "Источник: %(source)s" + +#: rapid/subfolderfile.py:339 +msgid "subfolder and filename" +msgstr "подкаталог и название файла" + +#: rapid/subfolderfile.py:377 +msgid "Failed to create download subfolder" +msgstr "" + +#: rapid/subfolderfile.py:378 +#, python-format +msgid "Path: %s" +msgstr "Путь: %s" + +#: rapid/glade3/rapid.ui.h:1 +msgid "About..." +msgstr "О программе" + +#: rapid/glade3/rapid.ui.h:2 +msgid "Check All" +msgstr "Выбрать всё" + +#: rapid/glade3/rapid.ui.h:3 +msgid "Check All Photos" +msgstr "Выбрать все фото" + +#: rapid/glade3/rapid.ui.h:4 +msgid "Check All Videos" +msgstr "Выбрать все видео" + +#: rapid/glade3/rapid.ui.h:5 +msgid "Download / Pause" +msgstr "Загрузка / Пауза" + +#: rapid/glade3/rapid.ui.h:6 +msgid "Get Help Online..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:7 +msgid "Make a Donation..." +msgstr "Сделать пожертвование..." + +#: rapid/glade3/rapid.ui.h:8 +msgid "Next File" +msgstr "Следующий файл" + +#: rapid/glade3/rapid.ui.h:9 +msgid "Previous File" +msgstr "Предыдущий файл" + +#: rapid/glade3/rapid.ui.h:10 +msgid "Quit" +msgstr "Выйти" + +#: rapid/glade3/rapid.ui.h:12 +msgid "Refresh" +msgstr "Обновить" + +#: rapid/glade3/rapid.ui.h:13 +msgid "Report a Problem..." +msgstr "Сообщить о проблеме..." + +#: rapid/glade3/rapid.ui.h:14 +msgid "Select All Wit_h Job Code" +msgstr "Выбрать всё с _метками" + +#: rapid/glade3/rapid.ui.h:15 +msgid "Select All Without _Job Code" +msgstr "Выбрать всё _без меток" + +#: rapid/glade3/rapid.ui.h:16 +msgid "Translate this Application..." +msgstr "" + +#: rapid/glade3/rapid.ui.h:17 +msgid "Uncheck All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:18 +msgid "_Check All" +msgstr "" + +#: rapid/glade3/rapid.ui.h:19 +msgid "_Clear Completed Downloads" +msgstr "_Убрать завершённые загрузки" + +#: rapid/glade3/rapid.ui.h:20 +msgid "_Download" +msgstr "_Загрузить" + +#: rapid/glade3/rapid.ui.h:21 +msgid "_Error Log" +msgstr "_Журнал ошибок" + +#: rapid/glade3/rapid.ui.h:22 +msgid "_File" +msgstr "_Файл" + +#: rapid/glade3/rapid.ui.h:23 +msgid "_Help" +msgstr "_Помощь" + +#: rapid/glade3/rapid.ui.h:24 +msgid "_Include in download" +msgstr "_Включить в загрузку" + +#: rapid/glade3/rapid.ui.h:25 +msgid "_Make a Donation..." +msgstr "_Сделать пожервование" + +#: rapid/glade3/rapid.ui.h:26 +msgid "_Select" +msgstr "_Выделить" + +#: rapid/glade3/rapid.ui.h:27 +msgid "_Translate this Application..." +msgstr "_Перевести это приложение..." + +#: rapid/glade3/rapid.ui.h:28 +msgid "_Uncheck All" +msgstr "_Снять все отметки" + +#: rapid/glade3/rapid.ui.h:29 +msgid "_View" +msgstr "_Просмотр" + +#: rapid/glade3/prefs.ui.h:1 msgid " " msgstr " " -#: rapid/glade3/rapid.glade.h:2 -msgid " " -msgstr " " - -#: rapid/glade3/rapid.glade.h:3 +#: rapid/glade3/prefs.ui.h:2 msgid " hh:mm" msgstr " чч:мм" -#: rapid/glade3/rapid.glade.h:4 +#: rapid/glade3/prefs.ui.h:3 msgid ":" msgstr ":" -#: rapid/glade3/rapid.glade.h:5 +#: rapid/glade3/prefs.ui.h:4 msgid "<b>Backup</b>" msgstr "<b>Резервное копирование</b>" -#: rapid/glade3/rapid.glade.h:6 +#: rapid/glade3/prefs.ui.h:5 msgid "<b>Compatibility with Other Operating Systems</b>" msgstr "<b>Совместимость с другими операционными системами</b>" -#: rapid/glade3/rapid.glade.h:7 +#: rapid/glade3/prefs.ui.h:6 msgid "<b>Devices</b>" msgstr "<b>Носители</b>" -#: rapid/glade3/rapid.glade.h:8 +#: rapid/glade3/prefs.ui.h:7 msgid "<b>Download Folder</b>" msgstr "<b>Каталог для загрузки фотографий</b>" -#: rapid/glade3/rapid.glade.h:9 +#: rapid/glade3/prefs.ui.h:8 msgid "<b>Download Subfolders</b>" msgstr "<b>Подкаталоги для загрузки фотографий</b>" -#: rapid/glade3/rapid.glade.h:10 +#: rapid/glade3/prefs.ui.h:9 msgid "<b>Example</b>" msgstr "<b>Пример</b>" -#: rapid/glade3/rapid.glade.h:11 +#: rapid/glade3/prefs.ui.h:10 msgid "<b>Job Codes</b>" msgstr "<b>Метки</b>" -#: rapid/glade3/rapid.glade.h:12 +#: rapid/glade3/prefs.ui.h:11 msgid "<b>Photo Rename</b>" msgstr "<b>Переименование фото</b>" -#: rapid/glade3/rapid.glade.h:13 +#: rapid/glade3/prefs.ui.h:12 msgid "<b>Photo and Video Name Conflicts</b>" msgstr "<b>Конфликт названий между фото и видео</b>" -#: rapid/glade3/rapid.glade.h:14 +#: rapid/glade3/prefs.ui.h:13 msgid "<b>Program Automation</b>" msgstr "<b>Автоматизация программы</b>" -#: rapid/glade3/rapid.glade.h:15 +#: rapid/glade3/prefs.ui.h:14 msgid "<b>Sequence Numbers</b>" msgstr "<b>Последовательности номеров</b>" -#: rapid/glade3/rapid.glade.h:16 +#: rapid/glade3/prefs.ui.h:15 msgid "<i>/media/externaldrive/Photos</i>" msgstr "<i>/media/externaldrive/Photos</i>" -#: rapid/glade3/rapid.glade.h:17 +#: rapid/glade3/prefs.ui.h:16 msgid "<i>Example: /home/user/Pictures</i>" msgstr "<i>Пример: /home/user/Pictures</i>" -#: rapid/glade3/rapid.glade.h:18 +#: rapid/glade3/prefs.ui.h:17 msgid "<i>Example:</i>" msgstr "<i>Пример:</i>" -#: rapid/glade3/rapid.glade.h:19 +#: rapid/glade3/prefs.ui.h:18 msgid "<i>New:</i>" msgstr "<i>Новое название:</i>" -#: rapid/glade3/rapid.glade.h:20 +#: rapid/glade3/prefs.ui.h:19 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 +#: rapid/glade3/prefs.ui.h:20 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 +#: rapid/glade3/prefs.ui.h:21 msgid "<span weight=\"bold\" size=\"x-large\">Devices</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Носители</span>" -#: rapid/glade3/rapid.glade.h:24 +#: rapid/glade3/prefs.ui.h:22 msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Обработка ошибок</span>" -#: rapid/glade3/rapid.glade.h:25 +#: rapid/glade3/prefs.ui.h:23 msgid "<span weight=\"bold\" size=\"x-large\">Job Codes</span>" msgstr "<span weight=\"bold\" size=\"x-large\">Метки</span>" -#: rapid/glade3/rapid.glade.h:26 +#: rapid/glade3/prefs.ui.h:24 +msgid "<span weight=\"bold\" size=\"x-large\">Miscellaneous</span>" +msgstr "" + +#: rapid/glade3/prefs.ui.h:25 msgid "<span weight=\"bold\" size=\"x-large\">Photo Download Folders</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Каталоги для загрузки фото</span>" -#: rapid/glade3/rapid.glade.h:27 +#: rapid/glade3/prefs.ui.h:26 msgid "<span weight=\"bold\" size=\"x-large\">Photo Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Переименование фото</span>\t" -#: rapid/glade3/rapid.glade.h:28 +#: rapid/glade3/prefs.ui.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:29 +#: rapid/glade3/prefs.ui.h:28 msgid "<span weight=\"bold\" size=\"x-large\">Video Download Folders</span>" msgstr "" "<span weight=\"bold\" size=\"x-large\">Каталоги для загрузки видео</span>" -#: rapid/glade3/rapid.glade.h:30 +#: rapid/glade3/prefs.ui.h:29 msgid "<span weight=\"bold\" size=\"x-large\">Video Rename</span>\t" msgstr "<span weight=\"bold\" size=\"x-large\">Переименование видео</span>\t" -#: rapid/glade3/rapid.glade.h:31 +#: rapid/glade3/prefs.ui.h:30 msgid "Add unique identifier" msgstr "Добавить уникальную метку" -#: rapid/glade3/rapid.glade.h:32 +#: rapid/glade3/prefs.ui.h:31 msgid "Automatically detect Portable Storage Devices" msgstr "Автоматически определять внешние съёмные носители" -#: rapid/glade3/rapid.glade.h:33 +#: rapid/glade3/prefs.ui.h:32 msgid "Automatically detect backup devices" msgstr "Автоматически определять носители для резервного копирования" -#: rapid/glade3/rapid.glade.h:34 +#: rapid/glade3/prefs.ui.h:33 msgid "Automatically detect devices" msgstr "Автоматически обнаруживать носители" -#: rapid/glade3/rapid.glade.h:35 -msgid "Automation" -msgstr "Автоматизация" - -#: rapid/glade3/rapid.glade.h:36 +#: rapid/glade3/prefs.ui.h:34 msgid "Backup" msgstr "Резервное копирование" -#: rapid/glade3/rapid.glade.h:37 +#: rapid/glade3/prefs.ui.h:35 msgid "Backup location:" msgstr "Местоположение резервных копий" -#: rapid/glade3/rapid.glade.h:38 +#: rapid/glade3/prefs.ui.h:36 msgid "Backup photos and videos when downloading" msgstr "" "Выполнять резервное копирование фотографий и видеороликов во время загрузки" -#: rapid/glade3/rapid.glade.h:39 +#: rapid/glade3/prefs.ui.h:37 msgid "" "Choose the download folder. Subfolders for the downloaded photos will be " "automatically created in this folder using the structure specified below." @@ -1667,7 +1502,7 @@ msgstr "" "загружаемых фотографий будут автоматически созданы в каждом каталоге, " "используя структуру, указанную вами ниже." -#: rapid/glade3/rapid.glade.h:40 +#: rapid/glade3/prefs.ui.h:38 msgid "" "Choose the download folder. Subfolders for the downloaded videos will be " "automatically created in this folder using the structure specified below." @@ -1676,23 +1511,19 @@ msgstr "" "загружаемых видеороликов будут автоматически созданы в каждом каталоге, " "используя структуру, указанную вами ниже." -#: rapid/glade3/rapid.glade.h:41 -msgid "Copyright Damon Lynch 2007-10" -msgstr "Авторские права Damon Lynch 2007-2010" - -#: rapid/glade3/rapid.glade.h:42 +#: rapid/glade3/prefs.ui.h:39 msgid "Day start:" msgstr "Начало дня:" -#: rapid/glade3/rapid.glade.h:43 +#: rapid/glade3/prefs.ui.h:40 msgid "Delete photos and videos from device upon download completion" msgstr "Удалить фото и видео после окончания загрузки" -#: rapid/glade3/rapid.glade.h:44 +#: rapid/glade3/prefs.ui.h:41 msgid "Devices" msgstr "Носители" -#: rapid/glade3/rapid.glade.h:45 +#: rapid/glade3/prefs.ui.h:42 msgid "" "Devices are from where to download photos and videos, such as cameras, " "memory cards or Portable Storage Devices.\n" @@ -1714,39 +1545,33 @@ msgstr "" "попробуйте преключить ее в режим PTP. Если это невозможно, используйте " "устройство для чтения карт памяти.</i>" -#: rapid/glade3/rapid.glade.h:50 -msgid "Download / Pause" -msgstr "Загрузка / Пауза" - -#: rapid/glade3/rapid.glade.h:51 +#: rapid/glade3/prefs.ui.h:47 msgid "Download folder:" msgstr "Каталог загрузки:" -#: rapid/glade3/rapid.glade.h:52 +#: rapid/glade3/prefs.ui.h:48 msgid "Downloads today:" msgstr "Загрузок сегодня:" -#: rapid/glade3/rapid.glade.h:53 +#: rapid/glade3/prefs.ui.h:49 msgid "Error Handling" msgstr "Обработка ошибок" -#: rapid/glade3/rapid.glade.h:54 -msgid "Error Log" -msgstr "Журнал ошибок" +#: rapid/glade3/prefs.ui.h:50 +msgid "Exit program even if download had warnings or errors" +msgstr "" -#: rapid/glade3/rapid.glade.h:55 -msgid "Exit program if download completes without any warnings or errors" +#: rapid/glade3/prefs.ui.h:51 +msgid "Exit program when download completes" msgstr "" -"Выйти из программы в том случае, если загрузка завершилась без " -"предупреждений и ошибок" -#: rapid/glade3/rapid.glade.h:56 +#: rapid/glade3/prefs.ui.h:52 msgid "If you disable automatic detection, choose the exact backup location." msgstr "" "Если вы отключаете автоматическое определение, то, пожалуйста, выберите " "точное местоположение носителя для резервного копирования." -#: rapid/glade3/rapid.glade.h:57 +#: rapid/glade3/prefs.ui.h:53 msgid "" "If you disable automatic detection, choose the exact location of the images " "and videos." @@ -1754,7 +1579,7 @@ msgstr "" "Если вы отключите автоматическое обнаружение, выберите точное местоположение " "фото и видео." -#: rapid/glade3/rapid.glade.h:58 +#: rapid/glade3/prefs.ui.h:54 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 " @@ -1764,118 +1589,55 @@ msgstr "" "просканированы на наличие фотографий. На носителях большого объёма это может " "занять достаточно много времени." -#: rapid/glade3/rapid.glade.h:59 -msgid "Import your photos and videos efficiently and reliably" -msgstr "Импортируйте ваши фото и видео быстро и надёжно" - -#: rapid/glade3/rapid.glade.h:60 +#: rapid/glade3/prefs.ui.h:55 msgid "Job Codes" msgstr "Метки" -#: rapid/glade3/rapid.glade.h:61 +#: rapid/glade3/prefs.ui.h:56 msgid "Location:" msgstr "Расположение:" -#: rapid/glade3/rapid.glade.h:62 +#: rapid/glade3/prefs.ui.h:57 +msgid "Miscillaneous" +msgstr "Разное" + +#: rapid/glade3/prefs.ui.h:58 msgid "Overwrite" msgstr "Перезаписать" -#: rapid/glade3/rapid.glade.h:63 -msgid "P_review Columns" -msgstr "Показывать к_олонки" - -#: rapid/glade3/rapid.glade.h:64 +#: rapid/glade3/prefs.ui.h:59 msgid "Photo Folders" msgstr "Каталоги фото" -#: rapid/glade3/rapid.glade.h:65 +#: rapid/glade3/prefs.ui.h:60 msgid "Photo Rename" msgstr "Переименование фото" -#: rapid/glade3/rapid.glade.h:66 +#: rapid/glade3/prefs.ui.h:61 msgid "Photo backup folder name:" msgstr "Название каталога резервного копирования фото" -#: rapid/glade3/rapid.glade.h:67 +#: rapid/glade3/prefs.ui.h:62 msgid "Preferences: Rapid Photo Downloader" msgstr "Настройки: Rapid Photo Downloader" -#: rapid/glade3/rapid.glade.h:68 -msgid "Preview _Folders" -msgstr "Показывать _каталоги" - -#: rapid/glade3/rapid.glade.h:70 +#: rapid/glade3/prefs.ui.h:64 msgid "R_emove All" msgstr "У_далить все" -#: rapid/glade3/rapid.glade.h:72 -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:77 +#: rapid/glade3/prefs.ui.h:65 msgid "Rename Options" msgstr "Параметры переименования" -#: rapid/glade3/rapid.glade.h:78 -msgid "Se_lect None" -msgstr "_Снять выделение" - -#: rapid/glade3/rapid.glade.h:79 -msgid "Select All Pho_tos" -msgstr "Выбрать все _фотографии" - -#: rapid/glade3/rapid.glade.h:80 -msgid "Select All Vi_deos" -msgstr "Выбрать все _видеоролики" - -#: rapid/glade3/rapid.glade.h:81 -msgid "Select All Wit_h Job Code" -msgstr "Выбрать всё с _метками" - -#: rapid/glade3/rapid.glade.h:82 -msgid "Select All Without _Job Code" -msgstr "Выбрать всё _без меток" - -#: rapid/glade3/rapid.glade.h:83 -msgid "Select _All" -msgstr "Выделить вс_ё" - -#: rapid/glade3/rapid.glade.h:84 +#: rapid/glade3/prefs.ui.h:66 msgid "Skip" msgstr "Пропустить" -#: rapid/glade3/rapid.glade.h:85 +#: rapid/glade3/prefs.ui.h:67 msgid "Skip download" msgstr "Пропустить загрузку" -#: rapid/glade3/rapid.glade.h:86 +#: rapid/glade3/prefs.ui.h:68 msgid "" "Sorry, video downloading functionality disabled. To download videos, please " "install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for " @@ -1885,7 +1647,7 @@ msgstr "" "пожалуйста, установите пакеты python <i>hachoir metadata</i> and <i>kaa " "metadata</i>." -#: rapid/glade3/rapid.glade.h:87 +#: rapid/glade3/prefs.ui.h:69 msgid "" "Specify the folder in which backups are stored on the device. \n" "\n" @@ -1899,7 +1661,7 @@ msgstr "" "резервного копирования. На каждом носителе, который вы хотите использовать " "для резервного копирования, создайте каталог с одним из этих имен.</i>" -#: rapid/glade3/rapid.glade.h:90 +#: rapid/glade3/prefs.ui.h:72 msgid "" "Specify the time in 24 hour format at which the <i>Downloads today</i> " "sequence number should be reset." @@ -1907,7 +1669,7 @@ msgstr "" "Укажите время в 24-часовом формате, когда следует обнулять параметр " "<i>Загрузок сегодня</i>." -#: rapid/glade3/rapid.glade.h:91 +#: rapid/glade3/prefs.ui.h:73 msgid "" "Specify whether photo, video and folder names should have any characters " "removed that are not allowed by other operating systems." @@ -1915,44 +1677,44 @@ msgstr "" "Укажите, следует ли удалить символы в названиях фото, видео, каталогов, " "которые не распознаются в других операционных системах." -#: rapid/glade3/rapid.glade.h:92 +#: rapid/glade3/prefs.ui.h:74 msgid "Start downloading at program startup" msgstr "" "Начать загрузку фотографий и видеороликов сразу после запуска программы" -#: rapid/glade3/rapid.glade.h:93 +#: rapid/glade3/prefs.ui.h:75 msgid "Start downloading upon device insertion" msgstr "Начать загрузку сразу после подключения носителя" -#: rapid/glade3/rapid.glade.h:94 +#: rapid/glade3/prefs.ui.h:76 msgid "Stored number:" msgstr "Сквозная нумерация:" -#: rapid/glade3/rapid.glade.h:95 +#: rapid/glade3/prefs.ui.h:77 msgid "Strip incompatible characters" msgstr "Убрать несовместимые символы" -#: rapid/glade3/rapid.glade.h:96 +#: rapid/glade3/prefs.ui.h:78 msgid "Synchronize RAW + JPEG sequence numbers" msgstr "Синхронизировать последовательность номеров при загрузке RAW + JPEG" -#: rapid/glade3/rapid.glade.h:97 +#: rapid/glade3/prefs.ui.h:79 msgid "Unmount (\"eject\") device upon download completion" msgstr "Отключить (\"извлечь\") носитель после завершения загрузки" -#: rapid/glade3/rapid.glade.h:98 +#: rapid/glade3/prefs.ui.h:80 msgid "Video Folders" msgstr "Каталоги видео" -#: rapid/glade3/rapid.glade.h:99 +#: rapid/glade3/prefs.ui.h:81 msgid "Video Rename" msgstr "Переименование видео" -#: rapid/glade3/rapid.glade.h:100 +#: rapid/glade3/prefs.ui.h:82 msgid "Video backup folder name:" msgstr "Название каталога резервного копирования видео" -#: rapid/glade3/rapid.glade.h:101 +#: rapid/glade3/prefs.ui.h:83 msgid "" "When a photo or video of the same name has already been downloaded, choose " "whether to skip downloading the file, or to add a unique indentifier." @@ -1960,7 +1722,7 @@ msgstr "" "Если фотография или видеоролик с таким названием уже загружен, выберите, " "пропустить загрузку или добавить уникальный идентификатор." -#: rapid/glade3/rapid.glade.h:102 +#: rapid/glade3/prefs.ui.h:84 msgid "" "When backing up, choose whether to overwrite a file on the backup device " "that has the same name, or skip backing it up." @@ -1968,7 +1730,7 @@ msgstr "" "Во время резервного копирования следует перезаписать файл, имеющий тоже " "самое название, или пропустить его?" -#: rapid/glade3/rapid.glade.h:103 +#: rapid/glade3/prefs.ui.h:85 msgid "" "You can have your photos and videos backed up to multiple locations as they " "are downloaded, e.g. external hard drives." @@ -1976,73 +1738,13 @@ msgstr "" "Имеется возможность создания резервной копии ваших фотографий и видеороликов " "прямо во время загрузки, в том числе на внешних жёстких дисках." -#: rapid/glade3/rapid.glade.h:104 +#: rapid/glade3/prefs.ui.h:86 msgid "_Add..." msgstr "_Добавить..." -#: rapid/glade3/rapid.glade.h:105 -msgid "_Clear Completed Downloads" -msgstr "_Убрать завершённые загрузки" - -#: rapid/glade3/rapid.glade.h:106 -msgid "_Device" -msgstr "_Носитель" - -#: rapid/glade3/rapid.glade.h:107 -msgid "_Error Log" -msgstr "_Журнал ошибок" - -#: rapid/glade3/rapid.glade.h:108 -msgid "_File" -msgstr "_Файл" - -#: rapid/glade3/rapid.glade.h:109 -msgid "_Filename" -msgstr "Имя файла" - -#: rapid/glade3/rapid.glade.h:110 -msgid "_Get Help Online..." -msgstr "_Получить помощь в интернете..." - -#: rapid/glade3/rapid.glade.h:111 -msgid "_Help" -msgstr "_Помощь" - -#: rapid/glade3/rapid.glade.h:112 -msgid "_Make a Donation..." -msgstr "_Сделать пожервование" - -#: rapid/glade3/rapid.glade.h:113 -msgid "_Path" -msgstr "_Путь" - -#: rapid/glade3/rapid.glade.h:114 -msgid "_Preview" -msgstr "П_редпросмотр" - -#: rapid/glade3/rapid.glade.h:115 -msgid "_Report a Problem..." -msgstr "_Сообщить о проблеме..." - -#: rapid/glade3/rapid.glade.h:116 -msgid "_Select" -msgstr "_Выделить" - -#: rapid/glade3/rapid.glade.h:117 -msgid "_Size" -msgstr "_Размер" - -#: rapid/glade3/rapid.glade.h:118 -msgid "_Translate this Application..." -msgstr "_Перевести это приложение..." - -#: rapid/glade3/rapid.glade.h:119 -msgid "_Type" -msgstr "_Тип" - -#: rapid/glade3/rapid.glade.h:120 -msgid "_View" -msgstr "_Просмотр" +#: rapid/glade3/about.ui.h:1 +msgid "Import your photos and videos efficiently and reliably" +msgstr "Импортируйте ваши фото и видео быстро и надёжно" #~ msgid "Could not open image" #~ msgstr "Не смог открыть фотографию" @@ -2058,6 +1760,12 @@ msgstr "_Просмотр" #~ msgid "%s images skipped" #~ msgstr "%s фотографий пропущено" +#~ msgid "errors" +#~ msgstr "ошибки" + +#~ msgid "Backing up error" +#~ msgstr "Ошибка резервного копирования" + #~ msgid "Image overwritten" #~ msgstr "Фотография перезаписана" @@ -2070,12 +1778,27 @@ msgstr "_Просмотр" #~ msgid "Image already exists" #~ msgstr "Фотография уже существует" +#~ msgid "Warning:" +#~ msgstr "Предупреждение:" + +#~ msgid "and" +#~ msgstr "и" + #~ msgid "images skipped" #~ msgstr "фотографий пропущено" +#~ msgid "_Pause" +#~ msgstr "_Пауза" + +#~ msgid "_Report a Problem..." +#~ msgstr "_Сообщить о проблеме..." + #~ msgid "_Photos" #~ msgstr "_Фотографии" +#~ msgid "_Get Help Online..." +#~ msgstr "_Получить помощь в интернете..." + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2104,6 +1827,12 @@ msgstr "_Просмотр" #~ "Фотография: %(image)s\n" #~ "Проблема: %(problem)s" +#~ msgid "Goodbye" +#~ msgstr "До свидания" + +#~ msgid " " +#~ msgstr " " + #~ msgid "<i>Example: /home/user/photos</i>" #~ msgstr "<i>Пример: /home/user/photos</i>" @@ -2113,6 +1842,9 @@ msgstr "_Просмотр" #~ msgid "Copyright Damon Lynch 2007-09" #~ msgstr "Copyright Damon Lynch 2007-09" +#~ msgid "Error Log" +#~ msgstr "Журнал ошибок" + #~ msgid "Ignore" #~ msgstr "Игнорировать" @@ -2129,12 +1861,35 @@ msgstr "_Просмотр" #~ "%(directory)s\n" #~ "Ошибка: %(errno)s %(strerror)s" +#~ msgid "Problem using pynotify." +#~ msgstr "Проблема при использовании pynotify." + +#~ msgid "Automation" +#~ msgstr "Автоматизация" + #~ msgid "Image Rename" #~ msgstr "Переименование фотографий" +#~ msgid "Resetting value to zero.\n" +#~ msgstr "Сбросить значение до нуля.\n" + #~ msgid "Select an image folder" #~ msgstr "Выберите каталог с фотографиями" +#, python-format +#~ msgid "%s is already running" +#~ msgstr "%s уже запущено" + +#~ msgid "Using" +#~ msgstr "Использование" + +#, python-format +#~ msgid "Detected %(device)s with path %(path)s" +#~ msgstr "Обнаружено %(device)s с путём %(path)s" + +#~ msgid "Sorry,these preferences contain an error:\n" +#~ msgstr "Извините, эти параметры содержат ошибку:\n" + #~ msgid "<b>Image Rename</b>" #~ msgstr "<b>Переименование фотографий</b>" @@ -2156,6 +1911,9 @@ msgstr "_Просмотр" #~ msgid "image number was specified but image filename has no number" #~ msgstr "номер фотографии был указано, но фотография не имеет номер" +#~ msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>" +#~ msgstr "<span weight=\"bold\" size=\"x-large\">Автоматизация</span>" + #~ msgid "<b>Image Devices</b>" #~ msgstr "<b>Носители фотографий</b>" @@ -2175,6 +1933,12 @@ msgstr "_Просмотр" #~ msgid "Automatically detect image devices" #~ msgstr "Автоматически определять носители, которые содержат фотографии" +#~ msgid "No backup devices detected" +#~ msgstr "Не обнаружено носителей для создания резервных копий" + +#~ msgid "Using backup devices" +#~ msgstr "Использование носителя для резервного копирования" + #~ msgid "Specify what to do when there are no backup devices." #~ msgstr "" #~ "Укажите, что делать если не обнаружены носители для резервного копирования." @@ -2183,6 +1947,9 @@ msgstr "_Просмотр" #~ msgid "Device scan complete: no images found on %s" #~ msgstr "Сканирование носителя %s завершено: фотографий не найдено" +#~ msgid "Using backup device" +#~ msgstr "Использование носителя для резервного копирования" + #~ msgid "Subsecond metadata not present in image" #~ msgstr "Метаданные подсекунд не представлены в фотографии" @@ -2190,6 +1957,9 @@ msgstr "_Просмотр" #~ msgid "%s metadata is not present in image" #~ msgstr "%s метаданные не представлены в фотографии" +#~ msgid "'Start of day' preference value is corrupted.\n" +#~ msgstr "Значение 'Начало дня' повреждено.\n" + #~ msgid "The subfolder preferences had some unnecessary values removed." #~ msgstr "" #~ "Параметры подкаталогов, имеющих некоторые ненужные значения, были удалены." @@ -2218,6 +1988,9 @@ msgstr "_Просмотр" #~ "Введённые параметры подкаталога неправильны и не могут быть использованы.\n" #~ "Они будут сброшены до значений принятых по умолчанию." +#~ msgid "Resetting to default values." +#~ msgstr "Восстановить настройки по умолчанию." + #~ msgid "" #~ "Image filename could not be properly generated. Check to ensure there is " #~ "sufficient image metadata." @@ -2240,6 +2013,19 @@ msgstr "_Просмотр" #~ "Название подкаталога не получилось сгенерировать должным образом. Проверьте " #~ "достаточно ли метаданных." +#~ msgid "The device can now be safely removed" +#~ msgstr "Теперь можно безопасно отсоединить носитель" + +#~ msgid "" +#~ "A newer version of this program was previously run on this computer.\n" +#~ "\n" +#~ msgstr "" +#~ "На этом компьютере ранее запускалась более новая версия программы.\n" +#~ "\n" + +#~ msgid "Failed to receive pynotify server capabilities." +#~ msgstr "Не удалось получить возможности сервера pynotify." + #, python-format #~ msgid "%s images downloaded" #~ msgstr "%s фотографий скачано" @@ -2375,6 +2161,10 @@ msgstr "_Просмотр" #~ msgid "Enter a new job code." #~ msgstr "Введите новую метку." +#, python-format +#~ msgid "Device %(device)s (%(path)s) ignored" +#~ msgstr "Носитель %(device)s (%(path)s) проигнорирован" + #~ msgid "No backup device was detected." #~ msgstr "Устройство для хранения резервных копий не обнаружено." @@ -2383,6 +2173,12 @@ msgstr "_Просмотр" #~ "Использовать ли этот носитель или диск как место, с которого скачиваются " #~ "фотографии?" +#~ msgid "Job Code not entered" +#~ msgstr "Метка не введена" + +#~ msgid "Job Code entered" +#~ msgstr "Метка введена" + #, python-format #~ msgid "Image: %(source)s" #~ msgstr "Изображение: %(source)s" @@ -2405,6 +2201,9 @@ msgstr "_Просмотр" #~ msgid "Delete images from image device upon download completion" #~ msgstr "Удалить изображения с устройства хранения после завершения закачки" +#~ msgid "Copyright Damon Lynch 2007-10" +#~ msgstr "Авторские права Damon Lynch 2007-2010" + #~ msgid "" #~ "When backing up, choose whether to overwrite an image on the backup device " #~ "that has the same name, or skip backing it up." @@ -2430,6 +2229,17 @@ msgstr "_Просмотр" #~ msgid "Image device: %s\n" #~ msgstr "Носитель изображений: %s\n" +#, python-format +#~ msgid "Source: %s\n" +#~ msgstr "Источник: %s\n" + +#~ msgid "Error:" +#~ msgstr "Ошибка:" + +#, python-format +#~ msgid "Error: %(errno)s %(strerror)s" +#~ msgstr "Ошибка: %(errno)s %(strerror)s" + #~ msgid "" #~ "Sorry, the Download Folder exists but cannot be written to. Please check the " #~ "folder's permissions, or modify your preferences" @@ -2458,6 +2268,12 @@ msgstr "_Просмотр" #~ "%(path)s\n" #~ "Пожалуйста, решите эту проблему или измените настройки" +#~ msgid "" +#~ "Warning: desktop environment notification server is incorrectly configured." +#~ msgstr "" +#~ "Внимание: сервер уведомлений вашего рабочего окружения не настроен " +#~ "надлежащим образом." + #, python-format #~ msgid "0 of %s images copied" #~ msgstr "0 из %s фотографий скачано" @@ -2469,6 +2285,10 @@ msgstr "_Просмотр" #~ msgid "%(number)s of %(total)s images copied" #~ msgstr "%(number)s из %(total)s фотографий скачано" +#, python-format +#~ msgid "Device: %s\n" +#~ msgstr "Носитель: %s\n" + #~ msgid "No backup device was automatically detected" #~ msgstr "" #~ "Не удалось автоматически обнаружить носитель для резервного копирования" @@ -2501,6 +2321,14 @@ msgstr "_Просмотр" #~ msgid "videos skipped" #~ msgstr "видеороликов пропущено" +#~ msgid "\n" +#~ msgstr "\n" + +#, python-format +#~ msgid "Device scan complete: no %(filetypes)s found on %(device)s" +#~ msgstr "" +#~ "Сканирование носителя завершено: %(filetypes)s не найдено на %(device)s" + #, python-format #~ msgid "0 of %(number)s %(filetypes)s" #~ msgstr "0 из %(number)s %(filetypes)s" @@ -2526,9 +2354,26 @@ msgstr "_Просмотр" #~ msgstr "Невозможно открыть %s(filetype)s" #, python-format +#~ msgid "Backup of %(file_type)s already exists" +#~ msgstr "Резервная копия %(file_type)s уже существует" + +#, python-format +#~ msgid "%(path)s: " +#~ msgstr "%(path)s: " + +#, python-format #~ msgid "%s metadata is not present in video" #~ msgstr "%s нет метаданных в видеоролике" +#~ msgid "Invalid Downloads Today value.\n" +#~ msgstr "Неверное значение 'Загрузок сегодня'.\n" + +#~ msgid "" +#~ "Downloads today value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Значение \"Загрузок сегодня\" не обновлено, так как загрузка идёт прямо " +#~ "сейчас" + #~ msgid "" #~ "Photos detected with the same filenames, but taken at different times:" #~ msgstr "" @@ -2541,6 +2386,54 @@ msgstr "_Просмотр" #~ msgid "Unique identifier '%s' added" #~ msgstr "Добавлена уникальная метка '%s'" +#~ msgid "New day has started - resetting 'Downloads Today' sequence number" +#~ msgstr "" +#~ "Начался новый день - сброшена последовательность номеров параметра 'Загрузок " +#~ "сегодня'" + +#~ msgid "Could not create temporary download directory" +#~ msgstr "Не удалось создать временный каталог для загрузки" + +#, python-format +#~ msgid "Download has started from %s" +#~ msgstr "Начата загрузка с %s" + +#, python-format +#~ msgid "Download complete from %s" +#~ msgstr "Загрузка с %s завершена" + +#, python-format +#~ msgid "%s selected for downloading from" +#~ msgstr "%s выбран для загрузки" + +#, python-format +#~ msgid "%s rejected as a download device" +#~ msgstr "%s не выбран для загрузки" + +#~ msgid "This device or partition will always be used to download from" +#~ msgstr "Этот носитель или раздел всегда будет использован для загрузки" + +#~ msgid "This device or partition will never be used to download from" +#~ msgstr "Этот носитель или раздел никогда не будет использован для загрузки" + +#~ msgid "Problem with Download Folders" +#~ msgstr "Проблема с каталогами для загрузки" + +#~ msgid "Problem with Download Folder" +#~ msgstr "Проблема с каталогом для загрузки" + +#~ msgid "Starting downloads" +#~ msgstr "Начинаются загрузки" + +#~ msgid "Starting downloads that have been waiting for a Job Code" +#~ msgstr "Начинаются загрузки, которые ожидали ввода метки" + +#~ msgid "Automatically start download is false" +#~ msgstr "Автоматически начинать загрузку - нет" + +#~ msgid "Automatically start download is true" +#~ msgstr "Автоматически начинать загрузку - да" + #~ msgid "videos downloaded" #~ msgstr "видеороликов загружено" @@ -2568,6 +2461,9 @@ msgstr "_Просмотр" #~ msgid "Photo thumbnail could not be extracted" #~ msgstr "Невозможно извлечь миниатюру фотографии" +#~ msgid "Backup path does not exist" +#~ msgstr "Путь резервного копирования не существует" + #, python-format #~ msgid "%s metadata is not present" #~ msgstr "%s метаданные не представлены" @@ -2579,6 +2475,10 @@ msgstr "_Просмотр" #~ "Не удаётся сгенерировать название подкаталога. Проверьте, хватает ли " #~ "метаданных." +#, python-format +#~ msgid "Deleted %(number)i %(filetypes)s from device" +#~ msgstr "Удалено %(number)i %(filetypes)s с носителя" + #~ msgid "" #~ "Choose whether to skip downloading the file, or to add a unique indentifier." #~ msgstr "" @@ -2606,6 +2506,33 @@ msgstr "_Просмотр" #~ "что метаданных хватает." #, python-format +#~ msgid "%(file_type)s not backed up to %(volume)s" +#~ msgstr "%(file_type)s не скопирован в резервную копию на %(volume)s" + +#, python-format +#~ msgid "%(file_type)s not backed up" +#~ msgstr "%(file_type)s не скопирован в резервную копию" + +#~ msgid "" +#~ "\n" +#~ "Please check preferences, restart the program, and try again." +#~ msgstr "" +#~ "\n" +#~ "Пожалуйста, проверьте настройки, перезапустите программу и попробуйте снова." + +#~ msgid "There is an error in the program preferences." +#~ msgstr "Обнаружена ошибка в настройках программы." + +#, python-format +#~ msgid "Device scan complete: found %(number)s %(filetypes)s on %(device)s" +#~ msgstr "" +#~ "Сканирование носителя завершено: найдено %(number)s %(filetypes)s на " +#~ "%(device)s" + +#~ msgid "The following download path could not be created:\n" +#~ msgstr "Указанный путь для загрузки файлов не может быть создан:\n" + +#, python-format #~ msgid "" #~ "Source: %(source)s\n" #~ "Partially generated filename: %(newname)s\n" @@ -2628,6 +2555,10 @@ msgstr "_Просмотр" #~ "Ошибка: %(errorno)s %(strerror)s" #, python-format +#~ msgid "Backup %(file_type)s overwritten" +#~ msgstr "Резервная копия %(file_type)s перезаписана" + +#, python-format #~ msgid "" #~ "Source: %(source)s\n" #~ "Destination: %(destination)s\n" @@ -2637,6 +2568,21 @@ msgstr "_Просмотр" #~ "Назначение: %(destination)s\n" #~ "Ошибка: %(errno)s %(strerror)s" +#~ msgid "A backup location was not found" +#~ msgstr "Не найдено указанное размещение для сохранения резервных копий" + +#, python-format +#~ msgid "%(file_type)s could not be backed up" +#~ msgstr "Резервная копия %(file_type)s не может быть создана." + +#, python-format +#~ msgid "The %(file_type)s was not backed up." +#~ msgstr "Резервная копия %(file_type)s не была создана." + +#, python-format +#~ msgid "Destination directory could not be created: %(directory)s\n" +#~ msgstr "Каталог назначения не может быть создан: %(directory)s\n" + #, python-format #~ msgid "" #~ "Source: %(source)s\n" @@ -2645,18 +2591,100 @@ msgstr "_Просмотр" #~ "Источник: %(source)s\n" #~ "Назначение: %(destination)s\n" +#~ msgid "No suitable backup volume was found" +#~ msgstr "Не найдено подходящего раздела для сохранения резервных копий" + +#, python-format +#~ msgid "Destination: %s" +#~ msgstr "Назначение: %s" + +#, python-format +#~ msgid "This device has no %(types_searched_for)s to download from." +#~ msgstr "Носитель не содержит %(types_searched_for)s для загрузки." + #~ msgid "Backup device missing" #~ msgstr "Отсутствует носитель для резервного копирования" +#~ msgid "No backups can occur" +#~ msgstr "Резервное копирование невозможно" + +#, python-format +#~ msgid "The path %s could not be created" +#~ msgstr "Не удалось создать путь %s" + #~ msgid "Enter a new job code, or select a previous one." #~ msgstr "Введите новую метку или выберите существующую." +#~ msgid "Problem with Device Location Folder" +#~ msgstr "Проблема с расположением носителя" + +#, python-format +#~ msgid "Prompting whether to use %s" +#~ msgstr "Спрашивать, использовать ли %s" + +#~ msgid "Already prompting for Job Code, do not prompt again" +#~ msgstr "Уже предложено использовать метку, больше не спрашивать" + +#~ msgid "Prompting for Job Code" +#~ msgstr "Предлагать использовать метку" + +#~ msgid "Some preferences will be reset." +#~ msgstr "Некоторые настройки будут сброшены." + +#~ msgid "" +#~ "Program preferences appear to be valid, but please check them to ensure " +#~ "correct operation." +#~ msgstr "" +#~ "Настройки программы выглядят верными, но проверьте их, чтобы увериться в " +#~ "правильной работе." + +#~ msgid "No preferences needed to be changed." +#~ msgstr "Настройки не требуют изменения." + +#~ 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" +#~ "Пожалуйста, проверьте их, чтобы быть увериться в правильной работе." + +#~ msgid "Preferences were modified." +#~ msgstr "Настройки были изменены" + +#~ msgid "" +#~ "This version of the program is newer than the previously run version. " +#~ "Checking preferences." +#~ msgstr "" +#~ "Эта версия программы новее, чем запущенная ранее. Проверьте настройки." + +#~ msgid "Using manually specified path" +#~ msgstr "Использовать указанный вручную путь" + #~ msgid "Preferences were changed." #~ msgstr "Настройки были изменены" +#~ msgid "These preferences are not well formed:" +#~ msgstr "Эти настройки не очень хорошо подобраны:" + #~ msgid "Subsecond metadata not present in photo" #~ msgstr "Метаданные о долях секунд отсутствуют в фотографии" +#, python-format +#~ msgid "Preference value '%(value)s' is invalid" +#~ msgstr "Неверное значение настроек '%(value)s'" + +#, python-format +#~ msgid "" +#~ "Preference key '%(key)s' is invalid.\n" +#~ "Expected one of %(value)s" +#~ msgstr "" +#~ "Неверен ключ настроек '%(key)s'.\n" +#~ "Ожидался один из %(value)s" + #~ msgid "image or video number was specified but filename has no number" #~ msgstr "" #~ "было обозначено использование номера фото или видео, но имя файл не содержит " @@ -2672,6 +2700,41 @@ msgstr "_Просмотр" #~ msgid "<b>Missing Backup Devices</b>" #~ msgstr "Отсутствует носитель для резервного копирования" +#~ msgid "Exit program if download completes without any warnings or errors" +#~ msgstr "" +#~ "Выйти из программы в том случае, если загрузка завершилась без " +#~ "предупреждений и ошибок" + +#~ 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." + #~ msgid "" #~ "Specify what to do when a photo or video of the same name has already been " #~ "downloaded or backed up." @@ -2679,5 +2742,252 @@ msgstr "_Просмотр" #~ "Укажите, что следует сделать, если фотография или видеоролик с таким же " #~ "названием уже были РАНЕЕ загружены или сохранены в резервную копию" +#, python-format +#~ msgid "" +#~ "The %(filetype)s subfolder preferences had some unnecessary values removed." +#~ msgstr "Некоторые излишние настройки подкаталога %(filetype)s удалены." + +#~ msgid "Stored number value not updated, as a download is currently occurring" +#~ msgstr "" +#~ "Счетчик сквозной нумерации не обновлен, так как прямо сейчас идёт загрузка" + +#~ msgid "_Show this message again" +#~ msgstr "_Показывать это сообщение снова" + +#~ msgid "Status" +#~ msgstr "Статус" + +#, python-format +#~ msgid "Error: %(inst)s" +#~ msgstr "Ошибка: %(inst)s" + +#~ msgid "File" +#~ msgstr "Файл" + +#~ msgid "Type" +#~ msgstr "Тип" + +#~ msgid "Path" +#~ msgstr "Путь" + +#~ msgid "Date" +#~ msgstr "Дата" + #~ msgid "Preview" #~ msgstr "Предварительный просмотр" + +#~ msgid "_Resume" +#~ msgstr "_Продолжить" + +#~ msgid "_Download All" +#~ msgstr "_Загрузить всё" + +#~ msgid "_Device" +#~ msgstr "_Носитель" + +#~ msgid "_Path" +#~ msgstr "_Путь" + +#~ msgid "_Preview" +#~ msgstr "П_редпросмотр" + +#~ msgid "_Size" +#~ msgstr "_Размер" + +#~ msgid "_Type" +#~ msgstr "_Тип" + +#, python-format +#~ msgid "Attempting to download %s files" +#~ msgstr "Попытка загрузить %s файлов" + +#~ msgid "Please check your system and try again." +#~ msgstr "Пожалуйста, проверьте вашу систему и попробуйте снова." + +#~ msgid "Downloading From Cameras" +#~ msgstr "Загрузка с камеры" + +#~ msgid "Downloading directly from a camera may work poorly or not at all" +#~ msgstr "" +#~ "Загрузка непосредственно с камеры может работать плохо или не работать вовсе" + +#~ msgid "Enter a new Job Code and press Enter, or select an existing Job Code" +#~ msgstr "Введите новую метку и нажмите Enter или выберите существующую метку" + +#~ msgid "D_ownload Selected" +#~ msgstr "З_агрузить отмеченное" + +#, python-format +#~ msgid "%(filetype)s was not downloaded" +#~ msgstr "%(filetype)s не загружено" + +#, python-format +#~ msgid "%(filetype)s was downloaded successfully" +#~ msgstr "%(filetype)s успешно загружено" + +#, python-format +#~ msgid "%(filetype)s was downloaded but there were problems backing up" +#~ msgstr "" +#~ "%(filetype)s загружено, но возникли проблемы с его резервным копированием" + +#, python-format +#~ msgid "%(filetype)s was downloaded with warnings" +#~ msgstr "%(filetype)s загружено с ошибками" + +#, python-format +#~ msgid "%(filetype)s will be downloaded with warnings" +#~ msgstr "%(filetype)s будет загружено с предупреждениями" + +#, python-format +#~ msgid "%(filetype)s was neither downloaded nor backed up" +#~ msgstr "%(filetype)s не был ни скачан, ни резервно скопирован" + +#, python-format +#~ msgid "Warning: backup device %(device)s is currently being downloaded from" +#~ msgstr "" +#~ "Внимание: с устройства для резервного копирования %(device)s в данный момент " +#~ "идет загрузка" + +#, python-format +#~ msgid "" +#~ "Source: %(source)s\n" +#~ "Destination: %(destination)s\n" +#~ "%(problem)s" +#~ msgstr "" +#~ "Источник: %(source)s\n" +#~ "Назначение: %(destination)s\n" +#~ "%(problem)s" + +#~ msgid "Backup preferences were changed." +#~ msgstr "Настройки резвервного копирования были изменены." + +#~ msgid "Select All Vi_deos" +#~ msgstr "Выбрать все _видеоролики" + +#~ msgid "Select All Pho_tos" +#~ msgstr "Выбрать все _фотографии" + +#~ msgid "Download device settings preferences were changed." +#~ msgstr "Настройки устройства загрузки были изменены." + +#~ msgid "Displaying warning about downloading directly from camera" +#~ msgstr "Отображает предупреждения о прямой загрузке с камеры" + +#, python-format +#~ msgid "The %(file_type)s Download Folder exists but cannot be written to.\n" +#~ msgstr "" +#~ "Каталог для загрузки %(file_type)s существует, но недоступен для записи.\n" + +#, python-format +#~ msgid "The %(file_type)s Download Folder does not exist.\n" +#~ msgstr "Каталог для загрузки %(file_type)s не существует.\n" + +#~ msgid "Preview _Folders" +#~ msgstr "Показывать _каталоги" + +#~ msgid "Subfolder and filename preferences were changed." +#~ msgstr "Настройки каталогов и названий файлов были изменены." + +#, python-format +#~ msgid "Photo: %(source)s" +#~ msgstr "Фото: %(source)s" + +#, python-format +#~ msgid "" +#~ "Photo: %(source)s\n" +#~ "Error: %(errno)s %(strerror)s" +#~ msgstr "" +#~ "Фото: %(source)s\n" +#~ "Ошибка: %(errno)s %(strerror)s" + +#, python-format +#~ msgid "Creating photo download folder %(folder)s" +#~ msgstr "Создание каталога для загрузки фото %(folder)s" + +#, python-format +#~ msgid "Failed to create default photo download folder %(folder)s" +#~ msgstr "Не удалось создать каталог для загрузки фото %(folder)s" + +#~ msgid "Could not delete photo or video from device" +#~ msgstr "Не удалось удалить фото или видео с носителя" + +#, python-format +#~ msgid "Failed to create default video download folder %(folder)s" +#~ msgstr "Не удалось создать каталог для загрузки видео %(folder)s" + +#, python-format +#~ msgid "Creating video download folder %(folder)s" +#~ msgstr "Создание каталога для загрузки видео %(folder)s" + +#, python-format +#~ msgid "%(filetype)s is ready to be downloaded" +#~ msgstr "%(filetype)s готово к загрузке" + +#~ msgid "Resetting to midnight.\n" +#~ msgstr "Вернуть значение \"полночь\".\n" + +#~ msgid "" +#~ "Downloading from a card reader always works and is generally much faster. It " +#~ "is strongly recommended to use a card reader." +#~ msgstr "" +#~ "Загрузка через картридер работает устойчиво и намного быстрее. Настоятельно " +#~ "рекомендуется использовать картридер." + +#, python-format +#~ msgid "%(filetype)s is about to be downloaded" +#~ msgstr "%(filetype)s ожидает загрузки" + +#, python-format +#~ msgid "%(filetype)s cannot be downloaded" +#~ msgstr "%(filetype)s не может быть загружено" + +#, python-format +#~ msgid "" +#~ "Sorry, this device location does not exist:\n" +#~ "%(path)s\n" +#~ "\n" +#~ "Please resolve the problem, or modify your preferences." +#~ msgstr "" +#~ "Извините, указанное расположение на носителя не существует:\n" +#~ "%(path)s\n" +#~ "Пожалуйста, исправьте ошибку или измените настройки" + +#~ msgid "" +#~ "Sorry, problems were encountered with your download folders. Please fix the " +#~ "problems or modify the preferences.\n" +#~ "\n" +#~ msgstr "" +#~ "Извините, были обнаружены проблемы с каталогами для загрузки. Пожалуйста, " +#~ "исправьте их или измените настройки.\n" +#~ "\n" + +#~ msgid "Sorry, some preferences are invalid and will be reset." +#~ msgstr "Извините, некоторые настройки неверны и будут сброшены." + +#~ 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 "" +#~ "Эта версия программы использует несколько другие настройки, чем предыдущая. " +#~ "Некоторые ваши настройки неверны и не могут быть обновлены. Они будут " +#~ "сброшены." + +#~ msgid "Download folder preferences were changed." +#~ msgstr "Настройки каталога для загрузки были изменены." + +#~ msgid "P_review Columns" +#~ msgstr "Показывать к_олонки" + +#~ msgid "Select _All" +#~ msgstr "Выделить вс_ё" + +#~ msgid "Se_lect None" +#~ msgstr "_Снять выделение" + +#~ msgid "_Filename" +#~ msgstr "Имя файла" + +#, python-format +#~ msgid "%(free)s available" +#~ msgstr "%(free)s доступно" diff --git a/rapid-photo-downloader b/rapid-photo-downloader index 87e63c0..b37ddf8 100755 --- a/rapid-photo-downloader +++ b/rapid-photo-downloader @@ -2,4 +2,4 @@ import rapid.rapid -rapid.rapid.start () +rapid.rapid.start() diff --git a/rapid/ChangeLog b/rapid/ChangeLog index 292d4b8..944119d 100644 --- a/rapid/ChangeLog +++ b/rapid/ChangeLog @@ -1,3 +1,66 @@ +Version 0.4.0 RC 1 +------------------ + +2011-04-21 + +Features added since beta 1: + +Backups have been implemented. If you are backing up to more than one device, +Rapid Photo Downloader will backup to each device simultaneously instead of one +after the other. + +When clicking the Download button before thumbnails are finished generating, +the download proceeds immediately and the thumbnails remaining to be generated +will rendered during the download itself. + +Added preferences option to disable thumbnail generation. When auto start is +enabled, this can speed-up transfers when downloading from high-speed devices. + +Access to the preferences window is now disable while a download is occurring, +as changing preferences when files are being download can cause prolems. + +Bug fix: don't crash when downloading some files after having previously +downloaded some others in the same session. + +Updated Brazilian, Dutch, German and Russian translations. + + +Version 0.4.0 beta 1 +-------------------- + +2011-04-10 + +Features added since alpha 4: + +* Job Code functionality, mimicking that found in version 0.2.3. +* Eject device button for each unmountable device in main window. +* When not all files have been downloaded from a device, the number remaining + is displayed in the device's progress bar +* Overall download progress is displayed in progress bar at bottom of window +* Time remaining and download speed are displayed in the status bar +* System notification messages +* Automation features: + * Automatically start a download at program startup or when a device + is inserted. When this is enabled, to optimize performance instead of + thumbnails being generated before the files are downloaded, they are + generated during the download. + * Eject a device when all files have been downloaded from it. + * Exit when all files have been downloaded. + +The automation feature to delete downloaded files from a device will be added +only when the non-alpha/beta of version 0.4.0 is released. + +The major feature currently not implemented is backups. + +Note: if videos are downloaded, the device may not be able to be unmounted +until Rapid Photo Downloader is exited. See bug #744012 for details. + +Bug fix: adjust vertical pane position when additional devices are inserted +Bug fix: display file and subfolder naming warnings in error log + +Updated Czech, French and Russian translations. + + Version 0.3.6 ------------- @@ -10,12 +73,102 @@ It also contains a minor packaging change so it can be installed in Ubuntu 11.04. +Version 0.4.0 alpha 4 +--------------------- + +2011-04-04 + +Fixed bug #750808: errorlog.ui not included in setup.py. + + +Version 0.4.0 alpha 3 +--------------------- + +2011-04-04 + +Features added since alpha 2: + +* Error log window to display download warnings and errors. +* Synchronize RAW + JPEG Sequence values. + +Fixed bug #739021: unable to set subfolder and file rename preferences on +alpha and beta Linux distributions such as Ubuntu 11.04 or Fedora 15. + +Updated Brazilian, Dutch, French, German and Spanish translations. + +Version 0.4.0 alpha 2 +--------------------- + +2011-03-31 + +Features added since alpha 1: + +* Sample file names and subfolders are now displayed in the preferences dialog + window. +* The option to add a unique identifier to a filename if a file with the same + name already exists + +Other changes: + +* Updated INSTALL file to match new package requirements. + +* Added program icon to main window. + +* Bug fix: leave file preview mode when download devices are changed in the + preferences. + +* Bug fix: don't crash on startup when trying to display free space and photo or + video download folders do not exist. + + +Version 0.4.0 alpha 1 +--------------------- + +2011-03-24 + +Rapid Photo Downloader is much faster and sports a new user interface. It is +about 50 times faster in tasks like scanning photos and videos before the +download. It also performs the actual downloads quicker. It will use +multiple CPU cores if they are available. + +Rapid Photo Downloader now requires version 0.3.0 or newer of pyexiv2. It also +requries Python Imaging (PIL) to run. It will only run on recent Linux +distributions such as Ubuntu 10.04 or newer. It has been tested on Ubuntu 10.04, +10.10 and 11.04, as well as Fedora 14. (There is currently an unusual bug +adjusting some preferences when running Ubuntu 11.04. See bug #739021). + +This is an alpha release because it is missing features that are present in +version 0.3.5. Missing features include: + +* System Notifications of download completion +* Job Codes +* Backups as you download +* Automation features, e.g. automatically start download at startup +* Error log window (currently you must check the command line for error output) +* Time remaining status messages +* Synchronize RAW + JPEG Sequence Numbers +* Add unique identifier to a filename if a file with the same name already + exists +* Sample file names and subfolders are not displayed in the preferences window + +These missing features will be added in subsequent alpha and beta releases. + +Kaa-metadata is no longer required to download videos. However, if you +want to use Frames Per Second or Codec metadata information in subfolder or +video file names, you must ensure it is installed. This is no longer checked at +program startup. + +Thanks go to Robert Park for refreshing the translations code. + +Added Romanian translation. + + Version 0.3.5 ------------- 2011-03-23 -The primary purpose of this release is update translations and fix bug #714039, +The primrary purpose of this release is update translations and fix bug #714039, where under certain circumstances the program could crash while downloading files. diff --git a/rapid/INSTALL b/rapid/INSTALL index 8270a20..8cde587 100644 --- a/rapid/INSTALL +++ b/rapid/INSTALL @@ -1,24 +1,15 @@ -Rapid Photo Downloader depends on the following software: - -- GNOME 2.18 or higher -- GTK+ 2.10 or higher -- Python 2.5 or 2.6 -- pygtk 2.12 or higher -- python-gconf 2.18 or higher -- python-glade2 2.12 or higher -- gnome-python 2.12 or higher -- libexiv2 0.15 or higher -- pyexiv2 0.1.1 or higher +Rapid Photo Downloader requires the following software: -To run Rapid Photo Downloader you will need all the software mentioned above. - -If you want to see dropshadows around thumbnail images, install python-imaging. -This is optional but recommended. +* Python 2.6 or 2.7 +* Pyexiv2 0.3.0 or higher +* python-gnome2 2.28 or higher +* python-gtk2 2.17 or higher +* python-gconf 2.28 or higher +* python-notify 0.1.1 or higher +* python-imaging 1.1.7 or higher +* librsvg2-common 2.26 or higher -A strongly recommended package is exiv2 (not just the library libexiv2), so -Rapid Photo Downloader can determine if it can download additional types of RAW -files (some early versions of exiv2 and pyexiv2 segfault on certain RAW file -types). +To run Rapid Photo Downloader you will need all the software mentioned above. If you want to download videos, you should install: @@ -29,7 +20,7 @@ If you want to download videos, you should install: hachoir metadata is required to download videos. kaa metadata is used to extract additional metadata from videos. ffmpegthumbnailer is used only to display thumbnail images before the download occurs. This is a useful feature, -and if you can install it, it is recommended. +and if you can install it, it is strongly recommended. hachoir metadata, kaa metadata and ffmpegthumbnailer are optional. The program will run without them. diff --git a/rapid/backupfile.py b/rapid/backupfile.py new file mode 100644 index 0000000..6b6d11d --- /dev/null +++ b/rapid/backupfile.py @@ -0,0 +1,187 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 multiprocessing +import tempfile +import os + +import gio + +import logging +logger = multiprocessing.get_logger() + +import rpdmultiprocessing as rpdmp +import rpdfile +import problemnotification as pn +import config + + +from gettext import gettext as _ + + +class BackupFiles(multiprocessing.Process): + def __init__(self, path, name, + batch_size_MB, results_pipe, terminate_queue, + run_event): + multiprocessing.Process.__init__(self) + self.results_pipe = results_pipe + self.terminate_queue = terminate_queue + self.batch_size_bytes = batch_size_MB * 1048576 # * 1024 * 1024 + self.path = path + self.mount_name = name + self.run_event = run_event + + def check_termination_request(self): + """ + Check to see this process has not been requested to immediately terminate + """ + if not self.terminate_queue.empty(): + x = self.terminate_queue.get() + # terminate immediately + logger.info("Terminating file backup") + return True + return False + + + def update_progress(self, amount_downloaded, total): + # first check if process is being terminated + self.amount_downloaded = amount_downloaded + if not self.terminate_queue.empty(): + # it is - cancel the current copy + self.cancel_copy.cancel() + else: + if not self.total_reached: + chunk_downloaded = amount_downloaded - self.bytes_downloaded + if (chunk_downloaded > self.batch_size_bytes) or (amount_downloaded == total): + self.bytes_downloaded = amount_downloaded + + if amount_downloaded == total: + # this function is called a couple of times when total is reached + self.total_reached = True + + self.results_pipe.send((rpdmp.CONN_PARTIAL, (rpdmp.MSG_BYTES, (self.scan_pid, self.pid, self.total_downloaded + amount_downloaded, chunk_downloaded)))) + if amount_downloaded == total: + self.bytes_downloaded = 0 + + def progress_callback(self, amount_downloaded, total): + self.update_progress(amount_downloaded, total) + + + def run(self): + + self.cancel_copy = gio.Cancellable() + self.bytes_downloaded = 0 + self.total_downloaded = 0 + + while True: + + self.amount_downloaded = 0 + move_succeeded, rpd_file, path_suffix, backup_duplicate_overwrite = self.results_pipe.recv() + if rpd_file is None: + # this is a termination signal + return None + # pause if instructed by the caller + self.run_event.wait() + + if self.check_termination_request(): + return None + + backup_succeeded = False + self.scan_pid = rpd_file.scan_pid + + if move_succeeded: + self.total_reached = False + + source = gio.File(path=rpd_file.download_full_file_name) + + if path_suffix is None: + dest_base_dir = self.path + else: + dest_base_dir = os.path.join(self.path, path_suffix) + + + dest_dir = os.path.join(dest_base_dir, rpd_file.download_subfolder) + backup_full_file_name = os.path.join( + dest_dir, + rpd_file.download_name) + + subfolder = gio.File(path=dest_dir) + if not subfolder.query_exists(cancellable=None): + # create the subfolders on the backup path + try: + subfolder.make_directory_with_parents(cancellable=gio.Cancellable()) + except gio.Error, inst: + # There is a tiny chance directory may have been created by + # another process between the time it takes to query and + # the time it takes to create a new directory. + # Ignore such errors. + if inst.code <> gio.ERROR_EXISTS: + logger.error("Failed to create backup subfolder: %s", dest_dir) + logger.error(inst) + rpd_file.add_problem(None, pn.BACKUP_DIRECTORY_CREATION, self.mount_name) + rpd_file.add_extra_detail('%s%s' % (pn.BACKUP_DIRECTORY_CREATION, self.mount_name), inst) + rpd_file.error_title = _('Backing up error') + rpd_file.error_msg = \ + _("Destination directory could not be created: %(directory)s\n") % \ + {'directory': subfolder, } + \ + _("Source: %(source)s\nDestination: %(destination)s") % \ + {'source': rpd_file.download_full_file_name, + 'destination': backup_full_file_name} + "\n" + \ + _("Error: %(inst)s") % {'inst': inst} + + dest = gio.File(path=backup_full_file_name) + if backup_duplicate_overwrite: + flags = gio.FILE_COPY_OVERWRITE + else: + flags = gio.FILE_COPY_NONE + + try: + source.copy(dest, self.progress_callback, flags, + cancellable=self.cancel_copy) + backup_succeeded = True + except gio.Error, inst: + fileNotBackedUpMessageDisplayed = True + rpd_file.add_problem(None, pn.BACKUP_ERROR, self.mount_name) + rpd_file.add_extra_detail('%s%s' % (pn.BACKUP_ERROR, self.mount_name), inst) + rpd_file.error_title = _('Backing up error') + rpd_file.error_msg = \ + _("Source: %(source)s\nDestination: %(destination)s") % \ + {'source': rpd_file.download_full_file_name, 'destination': backup_full_file_name} + "\n" + \ + _("Error: %(inst)s") % {'inst': inst} + logger.error("%s:\n%s", rpd_file.error_title, rpd_file.error_msg) + + if not backup_succeeded: + if rpd_file.status == config.STATUS_DOWNLOAD_FAILED: + rpd_file.status = config.STATUS_DOWNLOAD_AND_BACKUP_FAILED + else: + rpd_file.status = config.STATUS_BACKUP_PROBLEM + + self.total_downloaded += rpd_file.size + bytes_not_downloaded = rpd_file.size - self.amount_downloaded + if bytes_not_downloaded: + self.results_pipe.send((rpdmp.CONN_PARTIAL, (rpdmp.MSG_BYTES, (self.scan_pid, self.pid, self.total_downloaded, bytes_not_downloaded)))) + + self.results_pipe.send((rpdmp.CONN_PARTIAL, (rpdmp.MSG_FILE, + (backup_succeeded, rpd_file)))) + + + + + + diff --git a/rapid/common.py b/rapid/common.py deleted file mode 100644 index a55d835..0000000 --- a/rapid/common.py +++ /dev/null @@ -1,225 +0,0 @@ -#!/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 gtk -try: - import gio -except: - pass - -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 - -def get_icon_pixbuf(using_gio, icon, size, fallback='gtk-harddisk'): - """ returns icon for the volume, or None if not available""" - - icontheme = gtk.icon_theme_get_default() - - if using_gio: - f = None - if isinstance(icon, gio.ThemedIcon): - try: - # on some user's systems, themes do not have icons associated with them - iconinfo = icontheme.choose_icon(icon.get_names(), size, gtk.ICON_LOOKUP_USE_BUILTIN) - f = iconinfo.get_filename() - v = gtk.gdk.pixbuf_new_from_file_at_size(f, size, size) - except: - f = None - if not f: - v = icontheme.load_icon(fallback, size, gtk.ICON_LOOKUP_USE_BUILTIN) - else: - v = icontheme.load_icon(icon, size, gtk.ICON_LOOKUP_USE_BUILTIN) - return v - -def register_iconsets(icon_info): - """ - Register icons in the icon set if they're not already used - - From http://faq.pygtk.org/index.py?req=show&file=faq08.012.htp - """ - - iconfactory = gtk.IconFactory() - stock_ids = gtk.stock_list_ids() - for stock_id, file in icon_info: - # only load image files when our stock_id is not present - if stock_id not in stock_ids: - pixbuf = gtk.gdk.pixbuf_new_from_file(file) - iconset = gtk.IconSet(pixbuf) - iconfactory.add(stock_id, iconset) - iconfactory.add_default() - - - - -if __name__ == '__main__': - i = Configi18n() - _ = i._ - print _("hello world") diff --git a/rapid/config.py b/rapid/config.py index e798057..6019d6a 100644 --- a/rapid/config.py +++ b/rapid/config.py @@ -1,5 +1,5 @@ # -*- coding: latin1 -*- -### Copyright (C) 2007, 2008, 2009, 2010 Damon Lynch <damonlynch@gmail.com> +### Copyright (C) 2007, 2008, 2009, 2010, 2011 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 @@ -15,10 +15,9 @@ ### 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.3.6' +version = '0.4.0~rc1' GCONF_KEY="/apps/rapid-photo-downloader" -GLADE_FILE = "glade3/rapid.glade" DBUS_NAME = "net.damonlynch.RapidPhotoDownloader" @@ -38,18 +37,10 @@ DEFAULT_VIDEO_BACKUP_LOCATION = 'Videos' DEFAULT_VIDEO_LOCATIONS = ['Videos'] -MAX_NO_READERS = 20 - CRITICAL_ERROR = 1 SERIOUS_ERROR = 2 WARNING = 3 -MAX_LENGTH_DEVICE_NAME = 15 - -MIN_THUMBNAIL_SIZE = 80 -max_thumbnail_size = 320 # will be overridden when the screen is tiny -THUMBNAIL_INCREMENT = 50 - STATUS_DOWNLOAD_PENDING = 0 # going to try to download it STATUS_DOWNLOADED = 1 # downloaded successfully STATUS_DOWNLOADED_WITH_WARNING = 2 # downloaded ok but there was a warning @@ -60,4 +51,7 @@ STATUS_DOWNLOAD_FAILED = 6 # tried to download but failed STATUS_WARNING = 7 # warning (shown in pre-download preview) STATUS_CANNOT_DOWNLOAD = 8 # cannot be downloaded -TINY_SCREEN_HEIGHT = 650 +DEFAULT_WINDOW_WIDTH = 670 +DEFAULT_WINDOW_HEIGHT = 650 + + diff --git a/rapid/copyfiles.py b/rapid/copyfiles.py new file mode 100644 index 0000000..65a6c6d --- /dev/null +++ b/rapid/copyfiles.py @@ -0,0 +1,202 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 multiprocessing +import tempfile +import os + +import gio + +import logging +logger = multiprocessing.get_logger() + +import rpdmultiprocessing as rpdmp +import rpdfile +import problemnotification as pn +import config +import thumbnail as tn + + +from gettext import gettext as _ + + +class CopyFiles(multiprocessing.Process): + def __init__(self, photo_download_folder, video_download_folder, files, + scan_pid, + batch_size_MB, results_pipe, terminate_queue, + run_event): + multiprocessing.Process.__init__(self) + self.results_pipe = results_pipe + self.terminate_queue = terminate_queue + self.batch_size_bytes = batch_size_MB * 1048576 # * 1024 * 1024 + self.photo_download_folder = photo_download_folder + self.video_download_folder = video_download_folder + self.files = files + self.scan_pid = scan_pid + self.no_files= len(self.files) + self.run_event = run_event + + def check_termination_request(self): + """ + Check to see this process has not been requested to immediately terminate + """ + if not self.terminate_queue.empty(): + x = self.terminate_queue.get() + # terminate immediately + logger.info("Terminating file copying") + return True + return False + + + def update_progress(self, amount_downloaded, total): + # first check if process is being terminated + if not self.terminate_queue.empty(): + # it is - cancel the current copy + self.cancel_copy.cancel() + else: + if not self.total_reached: + chunk_downloaded = amount_downloaded - self.bytes_downloaded + if (chunk_downloaded > self.batch_size_bytes) or (amount_downloaded == total): + self.bytes_downloaded = amount_downloaded + if amount_downloaded == total: + # this function is called a couple of times when total is reached + self.total_reached = True + + self.results_pipe.send((rpdmp.CONN_PARTIAL, (rpdmp.MSG_BYTES, (self.scan_pid, self.total_downloaded + amount_downloaded, chunk_downloaded)))) + if amount_downloaded == total: + self.bytes_downloaded = 0 + + def progress_callback(self, amount_downloaded, total): + self.update_progress(amount_downloaded, total) + + + def run(self): + """start the actual copying of files""" + + self.bytes_downloaded = 0 + self.total_downloaded = 0 + + self.cancel_copy = gio.Cancellable() + + self.create_temp_dirs() + + # Send the location of both temporary directories, so they can be + # removed once another process attempts to rename all the files in them + # and move them to generated subfolders + self.results_pipe.send((rpdmp.CONN_PARTIAL, (rpdmp.MSG_TEMP_DIRS, + (self.scan_pid, + self.photo_temp_dir, + self.video_temp_dir)))) + + if self.photo_temp_dir or self.video_temp_dir: + + self.thumbnail_maker = tn.Thumbnail() + + for i in range(len(self.files)): + rpd_file = self.files[i] + self.total_reached = False + + # pause if instructed by the caller + self.run_event.wait() + + if self.check_termination_request(): + return None + + source = gio.File(path=rpd_file.full_file_name) + temp_full_file_name = os.path.join( + self._get_dest_dir(rpd_file.file_type), + rpd_file.name) + rpd_file.temp_full_file_name = temp_full_file_name + dest = gio.File(path=temp_full_file_name) + + copy_succeeded = False + try: + source.copy(dest, self.progress_callback, cancellable=self.cancel_copy) + copy_succeeded = True + except gio.Error, inst: + rpd_file.add_problem(None, + pn.DOWNLOAD_COPYING_ERROR_W_NO, + {'filetype': rpd_file.title}) + rpd_file.add_extra_detail( + pn.DOWNLOAD_COPYING_ERROR_W_NO_DETAIL, + {'errorno': inst.code, 'strerror': inst.message}) + + rpd_file.status = config.STATUS_DOWNLOAD_FAILED + + rpd_file.error_title = rpd_file.problem.get_title() + rpd_file.error_msg = _("%(problem)s\nFile: %(file)s") % \ + {'problem': rpd_file.problem.get_problems(), + 'file': rpd_file.full_file_name} + + logger.error("Failed to download file: %s", rpd_file.full_file_name) + logger.error(inst) + self.update_progress(rpd_file.size, rpd_file.size) + + # increment this amount regardless of whether the copy actually + # succeeded or not. It's neccessary to keep the user informed. + self.total_downloaded += rpd_file.size + + if copy_succeeded and rpd_file.generate_thumbnail: + thumbnail, thumbnail_icon = self.thumbnail_maker.get_thumbnail( + temp_full_file_name, + rpd_file.file_type, + (160, 120), (100,100)) + else: + thumbnail = None + thumbnail_icon = None + + if rpd_file.metadata is not None: + rpd_file.metadata = None + + self.results_pipe.send((rpdmp.CONN_PARTIAL, (rpdmp.MSG_FILE, + (copy_succeeded, rpd_file, i + 1, temp_full_file_name, + thumbnail_icon, thumbnail)))) + + + self.results_pipe.send((rpdmp.CONN_COMPLETE, None)) + + + def _get_dest_dir(self, file_type): + if file_type == rpdfile.FILE_TYPE_PHOTO: + return self.photo_temp_dir + else: + return self.video_temp_dir + + def _create_temp_dir(self, folder): + try: + temp_dir = tempfile.mkdtemp(prefix="rpd-tmp-", dir=folder) + except OSError, (errno, strerror): + # FIXME: error reporting + logger.error("Failed to create temporary directory in %s: %s %s", + errono, + strerror, + folder) + temp_dir = None + + return temp_dir + + def create_temp_dirs(self): + self.photo_temp_dir = self.video_temp_dir = None + if self.photo_download_folder is not None: + self.photo_temp_dir = self._create_temp_dir(self.photo_download_folder) + if self.video_download_folder is not None: + self.video_temp_dir = self._create_temp_dir(self.photo_download_folder) + + + diff --git a/rapid/device.py b/rapid/device.py new file mode 100644 index 0000000..dcfdf94 --- /dev/null +++ b/rapid/device.py @@ -0,0 +1,176 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 gtk, gio + +import multiprocessing +import logging +logger = multiprocessing.get_logger() + +import paths +import utilities + +from gettext import gettext as _ + +class Device: + def __init__(self, mount=None, path=None): + self.mount = mount + self.path = path + + def get_path(self): + if self.mount: + return self.mount.get_root().get_path() + else: + return self.path + + def get_name(self): + if self.mount: + return self.mount.get_name() + else: + return self.path + + def get_icon(self, size=16): + if self.mount: + icon = self.mount.get_icon() + else: + folder = gio.File(self.path) + file_info = folder.query_info(gio.FILE_ATTRIBUTE_STANDARD_ICON) + icon = file_info.get_icon() + + icontheme = gtk.icon_theme_get_default() + + icon_file = None + if isinstance(icon, gio.ThemedIcon): + try: + # on some user's systems, themes do not have icons associated with them + iconinfo = icontheme.choose_icon(icon.get_names(), size, gtk.ICON_LOOKUP_USE_BUILTIN) + icon_file = iconinfo.get_filename() + return gtk.gdk.pixbuf_new_from_file_at_size(icon_file, size, size) + except: + pass + + if not icon_file: + return icontheme.load_icon('folder', size, gtk.ICON_LOOKUP_USE_BUILTIN) + + +class UseDeviceDialog(gtk.Dialog): + """ + Simple dialog window that prompt's the user whether to use a certain + device or not + """ + def __init__(self, parent_window, device, post_choice_callback): + gtk.Dialog.__init__(self, _('Device Detected'), None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, + gtk.STOCK_YES, gtk.RESPONSE_OK)) + + self.post_choice_callback = post_choice_callback + + self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt + prompt_label = gtk.Label(_('Should this device or partition be used to download photos or videos from?')) + prompt_label.set_line_wrap(True) + prompt_hbox = gtk.HBox() + prompt_hbox.pack_start(prompt_label, False, False, padding=6) + device_label = gtk.Label() + device_label.set_markup("<b>%s</b>" % device.get_name()) + device_hbox = gtk.HBox() + device_hbox.pack_start(device_label, False, False) + path_label = gtk.Label() + path_label.set_markup("<i>%s</i>" % device.get_path()) + path_hbox = gtk.HBox() + path_hbox.pack_start(path_label, False, False) + + icon = device.get_icon(size=36) + if icon: + image = gtk.Image() + image.set_from_pixbuf(icon) + + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt + self.always_checkbutton = gtk.CheckButton(_('_Remember this choice'), True) + + if icon: + device_hbox_icon = gtk.HBox(homogeneous=False, spacing=6) + device_hbox_icon.pack_start(image, False, False, padding = 6) + device_vbox = gtk.VBox(homogeneous=True, spacing=6) + device_vbox.pack_start(device_hbox, False, False) + device_vbox.pack_start(path_hbox, False, False) + device_hbox_icon.pack_start(device_vbox, False, False) + self.vbox.pack_start(device_hbox_icon, padding = 6) + else: + self.vbox.pack_start(device_hbox, padding=6) + self.vbox.pack_start(path_hbox, padding = 6) + + self.vbox.pack_start(prompt_hbox, padding=6) + self.vbox.pack_start(self.always_checkbutton, padding=6) + + self.set_border_width(6) + self.set_has_separator(False) + + self.set_default_response(gtk.RESPONSE_OK) + + + self.set_transient_for(parent_window) + self.show_all() + self.device = device + + self.connect('response', self.on_response) + + def on_response(self, device_dialog, response): + user_selected = False + permanent_choice = self.always_checkbutton.get_active() + if response == gtk.RESPONSE_OK: + user_selected = True + logger.info("%s selected for downloading from", self.device.get_name()) + if permanent_choice: + logger.info("This device or partition will always be used to download from") + else: + logger.info("%s rejected as a download device", self.device.get_name()) + if permanent_choice: + logger.info("This device or partition will never be used to download from") + + self.post_choice_callback(self, user_selected, permanent_choice, + self.device) + + +def is_DCIM_device(path): + """ Returns true if directory specifies media with photos on it""" + + test_path = os.path.join(path, "DCIM") + return utilities.is_directory(test_path) + +def is_backup_media(path, identifiers, writeable=True): + """ Test to see if path is used as a backup medium for storing photos or videos + + Identifiers is expected to be a list of folder names to check to see + if the path is a backup path. Only one of them needs to be present + for the path to be considered a backup medium. + + If writeable is True, the directory must be writeable by the user """ + suitable = False + + for identifier in identifiers: + 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 + diff --git a/rapid/downloadtracker.py b/rapid/downloadtracker.py new file mode 100644 index 0000000..75c9c9d --- /dev/null +++ b/rapid/downloadtracker.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 time +from rpdfile import FILE_TYPE_PHOTO, FILE_TYPE_VIDEO +from config import STATUS_DOWNLOAD_FAILED, STATUS_DOWNLOADED_WITH_WARNING, \ + STATUS_DOWNLOAD_AND_BACKUP_FAILED, STATUS_BACKUP_PROBLEM + +from gettext import gettext as _ + +class DownloadTracker: + """ + Track file downloads - their size, number, and any problems + """ + def __init__(self): + self.file_types_present_by_scan_pid = dict() + self._refresh_values() + + def _refresh_values(self): + """ these values are reset when a download is completed""" + self.size_of_download_in_bytes_by_scan_pid = dict() + self.raw_size_of_download_in_bytes_by_scan_pid = dict() + self.total_bytes_copied_by_scan_pid = dict() + self.total_bytes_backed_up_by_scan_pid = dict() + self.no_files_in_download_by_scan_pid = dict() + + # 'Download count' tracks the index of the file being downloaded + # into the list of files that need to be downloaded -- much like + # a counter in a for loop, e.g. 'for i in list', where i is the counter + self.download_count_for_file_by_unique_id = dict() + self.download_count_by_scan_pid = dict() + self.rename_chunk = dict() + self.files_downloaded = dict() + self.photos_downloaded = dict() + self.videos_downloaded = dict() + self.photo_failures = dict() + self.video_failures = dict() + self.warnings = dict() + self.total_photos_downloaded = 0 + self.total_photo_failures = 0 + self.total_videos_downloaded = 0 + self.total_video_failures = 0 + self.total_warnings = 0 + self.total_bytes_to_download = 0 + self.backups_performed_by_unique_id = dict() + + def set_no_backup_devices(self, no_backup_devices): + self.no_backup_devices = no_backup_devices + + def init_stats(self, scan_pid, bytes, no_files): + self.no_files_in_download_by_scan_pid[scan_pid] = no_files + self.rename_chunk[scan_pid] = bytes / 10 / no_files + self.size_of_download_in_bytes_by_scan_pid[scan_pid] = bytes + self.rename_chunk[scan_pid] * no_files + self.raw_size_of_download_in_bytes_by_scan_pid[scan_pid] = bytes + self.total_bytes_to_download += self.size_of_download_in_bytes_by_scan_pid[scan_pid] + self.files_downloaded[scan_pid] = 0 + self.photos_downloaded[scan_pid] = 0 + self.videos_downloaded[scan_pid] = 0 + self.photo_failures[scan_pid] = 0 + self.video_failures[scan_pid] = 0 + self.warnings[scan_pid] = 0 + self.total_bytes_backed_up_by_scan_pid[scan_pid] = 0 + + def get_no_files_in_download(self, scan_pid): + return self.no_files_in_download_by_scan_pid[scan_pid] + + + def get_no_files_downloaded(self, scan_pid, file_type): + if file_type == FILE_TYPE_PHOTO: + return self.photos_downloaded.get(scan_pid, 0) + else: + return self.videos_downloaded.get(scan_pid, 0) + + def get_no_files_failed(self, scan_pid, file_type): + if file_type == FILE_TYPE_PHOTO: + return self.photo_failures.get(scan_pid, 0) + else: + return self.video_failures.get(scan_pid, 0) + + def get_no_warnings(self, scan_pid): + return self.warnings.get(scan_pid, 0) + + def file_backed_up(self, unique_id): + self.backups_performed_by_unique_id[unique_id] = \ + self.backups_performed_by_unique_id.get(unique_id, 0) + 1 + + def all_files_backed_up(self, unique_id): + v = self.backups_performed_by_unique_id[unique_id] == self.no_backup_devices + return v + + def file_downloaded_increment(self, scan_pid, file_type, status): + self.files_downloaded[scan_pid] += 1 + + if status <> STATUS_DOWNLOAD_FAILED and status <> STATUS_DOWNLOAD_AND_BACKUP_FAILED: + if file_type == FILE_TYPE_PHOTO: + self.photos_downloaded[scan_pid] += 1 + self.total_photos_downloaded += 1 + else: + self.videos_downloaded[scan_pid] += 1 + self.total_videos_downloaded += 1 + + if status == STATUS_DOWNLOADED_WITH_WARNING or status == STATUS_BACKUP_PROBLEM: + self.warnings[scan_pid] += 1 + self.total_warnings += 1 + else: + if file_type == FILE_TYPE_PHOTO: + self.photo_failures[scan_pid] += 1 + self.total_photo_failures += 1 + else: + self.video_failures[scan_pid] += 1 + self.total_video_failures += 1 + + + def get_percent_complete(self, scan_pid): + """ + Returns a float representing how much of the download + has been completed + """ + + # three components: copy (download), rename, and backup + percent_complete = (((float( + self.total_bytes_copied_by_scan_pid[scan_pid]) + + self.rename_chunk[scan_pid] * self.files_downloaded[scan_pid]) + + self.total_bytes_backed_up_by_scan_pid[scan_pid]) + / (self.size_of_download_in_bytes_by_scan_pid[scan_pid] + + self.raw_size_of_download_in_bytes_by_scan_pid[scan_pid] * + self.no_backup_devices)) * 100 + return percent_complete + + def get_overall_percent_complete(self): + total = 0 + for scan_pid in self.total_bytes_copied_by_scan_pid: + total += (self.total_bytes_copied_by_scan_pid[scan_pid] + + (self.rename_chunk[scan_pid] * + self.files_downloaded[scan_pid])) + + percent_complete = float(total) / self.total_bytes_to_download + return percent_complete + + def set_total_bytes_copied(self, scan_pid, total_bytes): + self.total_bytes_copied_by_scan_pid[scan_pid] = total_bytes + + def increment_bytes_backed_up(self, scan_pid, chunk_downloaded): + self.total_bytes_backed_up_by_scan_pid[scan_pid] += chunk_downloaded + + def set_download_count_for_file(self, unique_id, download_count): + self.download_count_for_file_by_unique_id[unique_id] = download_count + + def get_download_count_for_file(self, unique_id): + return self.download_count_for_file_by_unique_id[unique_id] + + def set_download_count(self, scan_pid, download_count): + self.download_count_by_scan_pid[scan_pid] = download_count + + def get_file_types_present(self, scan_pid): + return self.file_types_present_by_scan_pid[scan_pid] + + def set_file_types_present(self, scan_pid, file_types_present): + self.file_types_present_by_scan_pid[scan_pid] = file_types_present + + def no_errors_or_warnings(self): + """ + Return True if there were no errors or warnings in the download + else return False + """ + return (self.total_warnings == 0 and + self.total_photo_failures == 0 and + self.total_video_failures == 0) + + def purge(self, scan_pid): + del self.no_files_in_download_by_scan_pid[scan_pid] + del self.size_of_download_in_bytes_by_scan_pid[scan_pid] + del self.raw_size_of_download_in_bytes_by_scan_pid[scan_pid] + del self.photos_downloaded[scan_pid] + del self.videos_downloaded[scan_pid] + del self.files_downloaded[scan_pid] + del self.photo_failures[scan_pid] + del self.video_failures[scan_pid] + del self.warnings[scan_pid] + + def purge_all(self): + self._refresh_values() + + + +class TimeCheck: + """ + Record times downloads commmence and pause - used in calculating time + remaining. + + Also tracks and reports download speed. + + Note: This is completely independent of the file / subfolder naming + preference "download start time" + """ + + def __init__(self): + # set the number of seconds gap with which to measure download time remaing + self.download_time_gap = 3 + + self.reset() + + def reset(self): + self.mark_set = False + self.total_downloaded_so_far = 0 + self.total_download_size = 0 + self.size_mark = 0 + + def increment(self, bytes_downloaded): + self.total_downloaded_so_far += bytes_downloaded + + def set_download_mark(self): + if not self.mark_set: + self.mark_set = True + + self.time_mark = time.time() + + def pause(self): + self.mark_set = False + + def check_for_update(self): + now = time.time() + update = now > (self.download_time_gap + self.time_mark) + + if update: + amt_time = now - self.time_mark + self.time_mark = now + amt_downloaded = self.total_downloaded_so_far - self.size_mark + self.size_mark = self.total_downloaded_so_far + download_speed = "%1.1f" % (amt_downloaded / 1048576 / amt_time) +_("MB/s") + else: + download_speed = None + + return (update, download_speed) + +class TimeForDownload: + # used to store variables, see below + pass + +class TimeRemaining: + """ + Calculate how much time is remaining to finish a download + """ + gap = 3 + def __init__(self): + self.clear() + + def set(self, scan_pid, size): + t = TimeForDownload() + t.time_remaining = None + t.size = size + t.downloaded = 0 + t.size_mark = 0 + t.time_mark = time.time() + self.times[scan_pid] = t + + def update(self, scan_pid, bytes_downloaded): + if scan_pid in self.times: + self.times[scan_pid].downloaded += bytes_downloaded + now = time.time() + tm = self.times[scan_pid].time_mark + amt_time = now - tm + if amt_time > self.gap: + self.times[scan_pid].time_mark = now + amt_downloaded = self.times[scan_pid].downloaded - self.times[scan_pid].size_mark + self.times[scan_pid].size_mark = self.times[scan_pid].downloaded + timefraction = amt_downloaded / float(amt_time) + amt_to_download = float(self.times[scan_pid].size) - self.times[scan_pid].downloaded + if timefraction: + self.times[scan_pid].time_remaining = amt_to_download / timefraction + + def _time_estimates(self): + for t in self.times: + yield self.times[t].time_remaining + + def time_remaining(self): + return max(self._time_estimates()) + + def set_time_mark(self, scan_pid): + if scan_pid in self.times: + self.times[scan_pid].time_mark = time.time() + + def clear(self): + self.times = {} + + def remove(self, scan_pid): + if scan_pid in self.times: + del self.times[scan_pid] diff --git a/rapid/dropshadow.py b/rapid/dropshadow.py deleted file mode 100755 index 68b5398..0000000 --- a/rapid/dropshadow.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/python - - -import StringIO -import gtk -from PIL import Image, ImageFilter - -def image_to_pixbuf(image): - # this one handles transparency, unlike the default example in the pygtk FAQ - # this is also from the pygtk FAQ - IS_RGBA = image.mode=='RGBA' - return gtk.gdk.pixbuf_new_from_data( - image.tostring(), # data - gtk.gdk.COLORSPACE_RGB, # color mode - IS_RGBA, # has alpha - 8, # bits - image.size[0], # width - image.size[1], # height - (IS_RGBA and 4 or 3) * image.size[0] # rowstride - ) - - -def image_to_pixbuf_no_transparency(image): - fd = StringIO.StringIO() - image.save(fd, "ppm") - contents = fd.getvalue() - fd.close() - loader = gtk.gdk.PixbufLoader("pnm") - loader.write(contents, len(contents)) - pixbuf = loader.get_pixbuf() - loader.close() - return pixbuf - -def pixbuf_to_image(pb): - assert(pb.get_colorspace() == gtk.gdk.COLORSPACE_RGB) - dimensions = pb.get_width(), pb.get_height() - stride = pb.get_rowstride() - pixels = pb.get_pixels() - - mode = pb.get_has_alpha() and "RGBA" or "RGB" - image = Image.frombuffer(mode, dimensions, pixels, - "raw", mode, stride, 1) - - if mode == "RGB": - # convert to having an alpha value, so that the image can - # act as a mask in the drop shadow paste - image = image.convert("RGBA") - - return image - - -class DropShadow(): - """ - Adds a gaussian blur drop shadow to a PIL image. - - Caches backgrounds of particular sizes for improved performance. - - Backgrounds can be made transparent. - - Modification of code from Kevin Schluff and Matimus - License: Python license - See: - http://code.activestate.com/recipes/474116/ (r2) - http://bytes.com/topic/python/answers/606952-pil-paste-image-top-other-dropshadow - - """ - - def __init__(self, offset=(5,5), background_color=0xffffff, shadow = (0x44, 0x44, 0x44, 0xff), - border=8, iterations=3, trim_border=False): - """ - offset - Offset of the shadow from the image as an (x,y) tuple. Can be - positive or negative. - background_color - Background colour behind the image. - shadow - Shadow colour (darkness). - border - Width of the border around the image. This must be wide - enough to account for the blurring of the shadow. - trim_border - If true, the border will only be created on the - sides it needs to be (i.e. only on two sides) - iterations - Number of times to apply the filter. More iterations - produce a more blurred shadow, but increase processing time. - - To make backgrounds transparent, ensure the alpha value of the shadow color is the - same as the background color, e.g. if background_color is 0xffffff, shadow's alpha should be 0xff - - The image must be in RGBA format. - """ - self.backgrounds = {} - self.offset = offset - self.background_color = background_color - self.shadow = shadow - self.border = border - self.trim_border = trim_border - self.iterations = iterations - - if self.offset[0] < 0 or not self.trim_border: - self.left_spacing = self.border - else: - self.left_spacing = 0 - - if self.offset[1] < 0 or not self.trim_border: - self.top_spacing = self.border - else: - self.top_spacing = 0 - - def dropShadow(self, image): - """ - image - The image to overlay on top of the shadow. - """ - dimensions = (image.size[0], image.size[1]) - if not dimensions in self.backgrounds: - - # Create the backdrop image -- a box in the background colour with a - # shadow on it. - - if self.trim_border: - totalWidth = image.size[0] + abs(self.offset[0]) + self.border - totalHeight = image.size[1] + abs(self.offset[1]) + self.border - else: - totalWidth = image.size[0] + abs(self.offset[0]) + 2 * self.border - totalHeight = image.size[1] + abs(self.offset[1]) + 2 * self.border - - back = Image.new("RGBA", (totalWidth, totalHeight), self.background_color) - - # Place the shadow, taking into account the offset from the image - if self.offset[0] > 0 and self.trim_border: - shadowLeft = max(self.offset[0], 0) - else: - shadowLeft = self.border + max(self.offset[0], 0) - if self.offset[1] > 0 and self.trim_border: - shadowTop = max(self.offset[1], 0) - else: - shadowTop = self.border + max(self.offset[1], 0) - - back.paste(self.shadow, [shadowLeft, shadowTop, shadowLeft + image.size[0], - shadowTop + image.size[1]] ) - - # Apply the filter to blur the edges of the shadow. Since a small kernel - # is used, the filter must be applied repeatedly to get a decent blur. - n = 0 - while n < self.iterations: - back = back.filter(ImageFilter.BLUR) - n += 1 - - self.backgrounds[dimensions] = back - - # Paste the input image onto the shadow backdrop - imageLeft = self.left_spacing - min(self.offset[0], 0) - imageTop = self.top_spacing - min(self.offset[1], 0) - - back = self.backgrounds[dimensions].copy() - back.paste(image, (imageLeft, imageTop), image) - - return back - - - -if __name__ == "__main__": - import sys - import os - import common - - - # create another file with a drop shadow - f = sys.argv[1] - - image = Image.open(f) - image.thumbnail((60,36), Image.ANTIALIAS) - image2 = image.copy() - - path, name = os.path.split(f) - name, ext = os.path.splitext(name) - - #image = dropShadow(image, shadow = (0x44, 0x44, 0x44, 0xff)) - dropShadow = DropShadow(offset=(3,3), shadow = (0x34, 0x34, 0x34, 0xff), border=6) - image = dropShadow.dropShadow(image) - image2 = dropShadow.dropShadow(image2) - - nf = os.path.join(path, "%s_small_shadow%s" % (name, ext)) - nf2 = os.path.join(path, "%s_small_shadow2%s" % (name, ext)) - image.save(nf) - image2.save(nf2) - print "wrote %s , %s" % (nf, nf2) - diff --git a/rapid/errorlog.py b/rapid/errorlog.py new file mode 100644 index 0000000..0334465 --- /dev/null +++ b/rapid/errorlog.py @@ -0,0 +1,92 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 + +import pango +import config +import paths + +class ErrorLog(): + """ + Displays a log of errors, warnings or other information to the user + """ + + def __init__(self, rapidapp): + """ + Initialize values for log dialog, but do not display. + """ + + self.builder = gtk.Builder() + self.builder.add_from_file(paths.share_dir("glade3/errorlog.ui")) + self.builder.connect_signals(self) + self.widget = self.builder.get_object("errorlog") + self.log_textview = self.builder.get_object("log_textview") + self.log_scrolledwindow = self.builder.get_object("log_scrolledwindow") + + self.widget.connect("delete-event", self.hide_window) + + self.rapidapp = rapidapp + #~ self.log_textview.set_cursor_visible(False) + self.textbuffer = self.log_textview.get_buffer() + + self.error_tag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD, foreground="red") + self.warning_tag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD) + self.extra_detail_tag = self.textbuffer.create_tag(style=pango.STYLE_ITALIC) + + def add_message(self, severity, problem, details, extra_detail): + if severity in [config.CRITICAL_ERROR, config.SERIOUS_ERROR]: + self.rapidapp.error_image.show() + elif severity == config.WARNING: + self.rapidapp.warning_image.show() + self.rapidapp.warning_vseparator.show() + + iter = self.textbuffer.get_end_iter() + if severity in [config.CRITICAL_ERROR, config.SERIOUS_ERROR]: + self.textbuffer.insert_with_tags(iter, problem +"\n", self.error_tag) + else: + self.textbuffer.insert_with_tags(iter, problem +"\n", self.warning_tag) + if details: + iter = self.textbuffer.get_end_iter() + self.textbuffer.insert(iter, details + "\n") + if extra_detail: + iter = self.textbuffer.get_end_iter() + self.textbuffer.insert_with_tags(iter, extra_detail +"\n", self.extra_detail_tag) + + 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_errorlog_response(self, dialog, arg): + if arg == gtk.RESPONSE_CLOSE: + pass + self.rapidapp.error_image.hide() + self.rapidapp.warning_image.hide() + self.rapidapp.warning_vseparator.hide() + self.rapidapp.prefs.show_log_dialog = False + self.widget.hide() + return True + + def hide_window(self, window, event): + window.hide() + return True diff --git a/rapid/filmstrip.py b/rapid/filmstrip.py index 275fd1d..fc751fd 100755 --- a/rapid/filmstrip.py +++ b/rapid/filmstrip.py @@ -18,7 +18,7 @@ ### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ -Adds a filmstrip to the left and right of a file +Adds a filmstrip to the left and right of a pixbuf """ import gtk diff --git a/rapid/generatename.py b/rapid/generatename.py new file mode 100644 index 0000000..e904a70 --- /dev/null +++ b/rapid/generatename.py @@ -0,0 +1,480 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009, 2010, 2011 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, re, datetime, string, collections + +import multiprocessing +import logging +logger = multiprocessing.get_logger() + +import problemnotification as pn + +from generatenameconfig import * + +from gettext import gettext as _ + + +def convert_date_for_strftime(datetime_user_choice): + try: + return DATE_TIME_CONVERT[LIST_DATE_TIME_L2.index(datetime_user_choice)] + except: + raise PrefValueInvalidError(datetime_user_choice) + + +class PhotoName: + """ + Generate the name of a photo. Used as a base class for generating names + of videos, as well as subfolder names for both file types + """ + + def __init__(self, pref_list): + self.pref_list = pref_list + + + # Some of the next values are overwritten in derived classes + self.strip_initial_period_from_extension = False + self.strip_forward_slash = True + self.L1_date_check = IMAGE_DATE #used in _get_date_component() + self.component = pn.FILENAME_COMPONENT #used in error reporting + + + def _get_values_from_pref_list(self): + for i in range(0, len(self.pref_list), 3): + yield (self.pref_list[i], self.pref_list[i+1], self.pref_list[i+2]) + + def _get_date_component(self): + """ + Returns portion of new file / subfolder name based on date time. + If the date is missing, will attempt to use the fallback date. + """ + + # step 1: get the correct value from metadata + if self.L1 == self.L1_date_check: + if self.L2 == SUBSECONDS: + d = self.rpd_file.metadata.sub_seconds() + if d == '00': + self.rpd_file.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L2)) + return '' + else: + return d + else: + d = self.rpd_file.metadata.date_time(missing=None) + + elif self.L1 == TODAY: + d = datetime.datetime.now() + elif self.L1 == YESTERDAY: + delta = datetime.timedelta(days = 1) + d = datetime.datetime.now() - delta + elif self.L1 == DOWNLOAD_TIME: + d = self.rpd_file.download_start_time + else: + raise("Date options invalid") + + # step 2: if have a value, try to convert it to string format + if d: + try: + return d.strftime(convert_date_for_strftime(self.L2)) + except: + logger.warning("Exif date time value appears invalid for file %s", self.rpd_file.full_file_name) + + # step 3: handle a missing value using file modification time + if self.rpd_file.modification_time: + try: + d = datetime.datetime.fromtimestamp(self.rpd_file.modification_time) + except: + self.rpd_file.add_problem(self.component, pn.INVALID_DATE_TIME, '') + logger.error("Both file modification time and metadata date & time are invalid for file %s", self.rpd_file.full_file_name) + return '' + else: + self.rpd_file.add_problem(self.component, pn.MISSING_METADATA, _(self.L1)) + return '' + + try: + return d.strftime(convert_date_for_strftime(self.L2)) + except: + self.rpd_file.add_problem(self.component, pn.INVALID_DATE_TIME, d) + logger.error("Both file modification time and metadata date & time are invalid for file %s", self.rpd_file.full_file_name) + return '' + + def _get_filename_component(self): + """ + Returns portion of new file / subfolder name based on the file name + """ + + name, extension = os.path.splitext(self.rpd_file.name) + + if self.L1 == NAME_EXTENSION: + filename = self.rpd_file.name + elif self.L1 == NAME: + filename = name + elif self.L1 == EXTENSION: + if extension: + if not self.strip_initial_period_from_extension: + # 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 when it is at the start! + filename = extension[1:] + else: + self.rpd_file.add_problem(self.component, pn.MISSING_FILE_EXTENSION) + return "" + elif self.L1 == IMAGE_NUMBER or self.L1 == VIDEO_NUMBER: + n = re.search("(?P<image_number>[0-9]+$)", name) + if not n: + self.rpd_file.add_problem(self.component, pn.MISSING_IMAGE_NUMBER) + return '' + 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 + + def _get_metadata_component(self): + """ + Returns portion of new image / subfolder name based on the metadata + + Note: date time metadata found in _getDateComponent() + """ + + if self.L1 == APERTURE: + v = self.rpd_file.metadata.aperture() + elif self.L1 == ISO: + v = self.rpd_file.metadata.iso() + elif self.L1 == EXPOSURE_TIME: + v = self.rpd_file.metadata.exposure_time(alternativeFormat=True) + elif self.L1 == FOCAL_LENGTH: + v = self.rpd_file.metadata.focal_length() + elif self.L1 == CAMERA_MAKE: + v = self.rpd_file.metadata.camera_make() + elif self.L1 == CAMERA_MODEL: + v = self.rpd_file.metadata.camera_model() + elif self.L1 == SHORT_CAMERA_MODEL: + v = self.rpd_file.metadata.short_camera_model() + elif self.L1 == SHORT_CAMERA_MODEL_HYPHEN: + v = self.rpd_file.metadata.short_camera_model(includeCharacters = "\-") + elif self.L1 == SERIAL_NUMBER: + v = self.rpd_file.metadata.camera_serial() + elif self.L1 == SHUTTER_COUNT: + v = self.rpd_file.metadata.shutter_count() + 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.rpd_file.metadata.owner_name() + 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: + self.rpd_file.add_problem(self.component, pn.MISSING_METADATA, _(self.L1)) + return v + + def _calculate_letter_sequence(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 _format_sequence_no(self, value, amountToPad): + padding = LIST_SEQUENCE_NUMBERS_L2.index(amountToPad) + 1 + formatter = '%0' + str(padding) + "i" + return formatter % value + + def _get_downloads_today(self): + return self._format_sequence_no(self.rpd_file.sequences.get_downloads_today(), self.L2) + + def _get_session_sequence_no(self): + return self._format_sequence_no(self.rpd_file.sequences.get_session_sequence_no(), self.L2) + + def _get_stored_sequence_no(self): + return self._format_sequence_no(self.rpd_file.sequences.get_stored_sequence_no(), self.L2) + + def _get_sequence_letter(self): + return self._calculate_letter_sequence(self.rpd_file.sequences.get_sequence_letter()) + + def _get_sequences_component(self): + if self.L1 == DOWNLOAD_SEQ_NUMBER: + return self._get_downloads_today() + elif self.L1 == SESSION_SEQ_NUMBER: + return self._get_session_sequence_no() + elif self.L1 == STORED_SEQ_NUMBER: + return self._get_stored_sequence_no() + elif self.L1 == SEQUENCE_LETTER: + return self._get_sequence_letter() + + + #~ elif self.L1 == SUBFOLDER_SEQ_NUMBER: + #~ return self._getSubfolderSequenceNo() + + + + def _get_component(self): + try: + if self.L0 == DATE_TIME: + return self._get_date_component() + elif self.L0 == TEXT: + return self.L1 + elif self.L0 == FILENAME: + return self._get_filename_component() + elif self.L0 == METADATA: + return self._get_metadata_component() + elif self.L0 == SEQUENCES: + return self._get_sequences_component() + elif self.L0 == JOB_CODE: + return self.rpd_file.job_code + elif self.L0 == SEPARATOR: + return os.sep + except: + self.rpd_file.add_problem(self.component, pn.ERROR_IN_GENERATION, _(self.L0)) + return '' + + + def generate_name(self, rpd_file): + self.rpd_file = rpd_file + + name = '' + + for self.L0, self.L1, self.L2 in self._get_values_from_pref_list(): + v = self._get_component() + if v: + name += v + + if self.rpd_file.strip_characters: + for c in r'\:*?"<>|': + name = name.replace(c, '') + + if self.strip_forward_slash: + name = name.replace('/', '') + + name = name.strip() + + return name + + + + +class VideoName(PhotoName): + def __init__(self, pref_list): + PhotoName.__init__(self, pref_list) + self.L1_date_check = VIDEO_DATE #used in _get_date_component() + + def _get_metadata_component(self): + """ + Returns portion of video / subfolder name based on the metadata + + Note: date time metadata found in _getDateComponent() + """ + return get_video_metadata_component(self) + +class PhotoSubfolder(PhotoName): + """ + Generate subfolder names for photo files + """ + + def __init__(self, pref_list): + self.pref_list = pref_list + + self.strip_extraneous_white_space = re.compile(r'\s*%s\s*' % os.sep) + self.strip_initial_period_from_extension = True + self.strip_forward_slash = False + self.L1_date_check = IMAGE_DATE #used in _get_date_component() + self.component = pn.SUBFOLDER_COMPONENT #used in error reporting + + def generate_name(self, rpd_file): + + subfolders = PhotoName.generate_name(self, rpd_file) + + # 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:] + + # remove any spaces before and after a directory name + if subfolders and self.rpd_file.strip_characters: + subfolders = self.strip_extraneous_white_space.sub(os.sep, subfolders) + + return subfolders + + + + +class VideoSubfolder(PhotoSubfolder): + """ + Generate subfolder names for video files + """ + + def __init__(self, pref_list): + PhotoSubfolder.__init__(self, pref_list) + self.L1_date_check = VIDEO_DATE #used in _get_date_component() + + + def _get_metadata_component(self): + """ + Returns portion of video / subfolder name based on the metadata + + Note: date time metadata found in _getDateComponent() + """ + return get_video_metadata_component(self) + +def get_video_metadata_component(video): + """ + Returns portion of video / subfolder name based on the metadata + + This is outside of a class definition because of the inheritence + hierarchy. + """ + + problem = None + if video.L1 == CODEC: + v = video.rpd_file.metadata.codec() + elif video.L1 == WIDTH: + v = video.rpd_file.metadata.width() + elif video.L1 == HEIGHT: + v = video.rpd_file.metadata.height() + elif video.L1 == FPS: + v = video.rpd_file.metadata.frames_per_second() + elif video.L1 == LENGTH: + v = video.rpd_file.metadata.length() + else: + raise TypeError("Invalid metadata option specified") + if video.L1 in [CODEC]: + if video.L2 == UPPERCASE: + v = v.upper() + elif video.L2 == LOWERCASE: + v = v.lower() + if not v: + video.rpd_file.add_problem(video.component, pn.MISSING_METADATA, _(video.L1)) + return v + +class Sequences: + """ + Holds sequence numbers and letters used in generating filenames. + """ + def __init__(self, downloads_today_tracker, stored_sequence_no): + self.session_sequence_no = 0 + self.sequence_letter = -1 + self.downloads_today_tracker = downloads_today_tracker + self.stored_sequence_no = stored_sequence_no + self.matched_sequences = None + + def set_matched_sequence_value(self, matched_sequences): + self.matched_sequences = matched_sequences + + def get_session_sequence_no(self): + if self.matched_sequences is not None: + return self.matched_sequences.session_sequence_no + else: + return self._get_session_sequence_no() + + def _get_session_sequence_no(self): + return self.session_sequence_no + 1 + + def get_sequence_letter(self): + if self.matched_sequences is not None: + return self.matched_sequences.sequence_letter + else: + return self._get_sequence_letter() + + def _get_sequence_letter(self): + return self.sequence_letter + 1 + + def increment(self, uses_session_sequece_no, uses_sequence_letter): + if uses_session_sequece_no: + self.session_sequence_no += 1 + if uses_sequence_letter: + self.sequence_letter += 1 + + def get_downloads_today(self): + if self.matched_sequences is not None: + return self.matched_sequences.downloads_today + else: + return self._get_downloads_today() + + def _get_downloads_today(self): + v = self.downloads_today_tracker.get_downloads_today() + if v == -1: + return 1 + else: + return v + 1 + + def get_stored_sequence_no(self): + if self.matched_sequences is not None: + return self.matched_sequences.stored_sequence_no + else: + return self._get_stored_sequence_no() + + def _get_stored_sequence_no(self): + # Must add 1 to the value, for historic reasons (that is how it used + # to work) + return self.stored_sequence_no + 1 + + def create_matched_sequences(self): + sequences = collections.namedtuple( + 'AssignedSequences', + 'session_sequence_no sequence_letter downloads_today stored_sequence_no' + ) + sequences.session_sequence_no = self._get_session_sequence_no() + sequences.sequence_letter = self._get_sequence_letter() + sequences.downloads_today = self._get_downloads_today() + sequences.stored_sequence_no = self._get_stored_sequence_no() + return sequences diff --git a/rapid/generatenameconfig.py b/rapid/generatenameconfig.py new file mode 100644 index 0000000..321761e --- /dev/null +++ b/rapid/generatenameconfig.py @@ -0,0 +1,482 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009, 2010, 2011 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 + +# 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. + +import os + +from gettext import gettext as _ + +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 you MUST change the value in class i18TranslateMeThanks as well!! + +# *** Level 0 +DATE_TIME = 'Date time' +TEXT = 'Text' +FILENAME = 'Filename' +METADATA = 'Metadata' +SEQUENCES = 'Sequences' +JOB_CODE = 'Job code' + +SEPARATOR = os.sep + +# *** Level 1 + +# Date time +IMAGE_DATE = 'Image date' +TODAY = 'Today' +YESTERDAY = 'Yesterday' +VIDEO_DATE = 'Video date' +DOWNLOAD_TIME = 'Download time' + +# File name +NAME_EXTENSION = 'Name + extension' +NAME = 'Name' +EXTENSION = 'Extension' +IMAGE_NUMBER = 'Image number' +VIDEO_NUMBER = 'Video 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' + +# Video metadata +CODEC = 'Codec' +WIDTH = 'Width' +HEIGHT = 'Height' +FPS = 'Frames Per Second' +LENGTH = 'Length' + +#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" +SEQUENCE_NUMBER_7 = "Seven digits" + + +# Now, define dictionaries and lists of valid combinations of preferences. + +# Level 2 + +# Date + +SUBSECONDS = 'Subseconds' + +# ****** NOTE 1: if changing LIST_DATE_TIME_L2, you MUST update the default subfolder preference below ***** +# ****** NOTE 2: if changing LIST_DATE_TIME_L2, you MUST update DATE_TIME_CONVERT below ***** +LIST_DATE_TIME_L2 = ['YYYYMMDD', 'YYYY-MM-DD','YYMMDD', 'YY-MM-DD', + 'MMDDYYYY', 'MMDDYY', 'MMDD', + 'DDMMYYYY', 'DDMMYY', 'YYYY', 'YY', + 'MM', 'DD', + 'HHMMSS', 'HHMM', 'HH-MM-SS', 'HH-MM', 'HH', 'MM (minutes)', 'SS'] + + +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]] +DEFAULT_VIDEO_SUBFOLDER_PREFS = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[9], '/', '', '', DATE_TIME, VIDEO_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') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode + _('Job code') + _('Image date') + _('Video date') + _('Today') + _('Yesterday') + # Translators: Download time is the time and date that the download started (when the user clicked the Download button) + _('Download time') + # 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') + _('Video 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') + _('Codec') + _('Width') + _('Height') + _('Length') + _('Frames Per Second') + # 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") + _("Seven 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') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('HH-MM-SS') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('HH-MM') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('HH') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('MM (minutes)') + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime + _('SS') + + +# 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', '%H-%M-%S', '%H-%M', + '%H', '%M', '%S'] + + +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, + SEQUENCE_NUMBER_7, + ] + + + +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, DOWNLOAD_TIME] +LIST_VIDEO_DATE_TIME_L1 = [VIDEO_DATE, TODAY, YESTERDAY, DOWNLOAD_TIME] + +DICT_DATE_TIME_L1 = { + IMAGE_DATE: LIST_IMAGE_DATE_TIME_L2, + TODAY: LIST_DATE_TIME_L2, + YESTERDAY: LIST_DATE_TIME_L2, + DOWNLOAD_TIME: LIST_DATE_TIME_L2, + ORDER_KEY: LIST_DATE_TIME_L1 + } + +VIDEO_DICT_DATE_TIME_L1 = { + VIDEO_DATE: LIST_IMAGE_DATE_TIME_L2, + TODAY: LIST_DATE_TIME_L2, + YESTERDAY: LIST_DATE_TIME_L2, + DOWNLOAD_TIME: LIST_DATE_TIME_L2, + ORDER_KEY: LIST_VIDEO_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_VIDEO_FILENAME_L1 = [NAME_EXTENSION, NAME, EXTENSION, VIDEO_NUMBER] + +DICT_VIDEO_FILENAME_L1 = { + NAME_EXTENSION: LIST_CASE_L2, + NAME: LIST_CASE_L2, + EXTENSION: LIST_CASE_L2, + VIDEO_NUMBER: LIST_IMAGE_NUMBER_L2, + ORDER_KEY: LIST_VIDEO_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] + +LIST_VIDEO_METADATA_L1 = [CODEC, WIDTH, HEIGHT, LENGTH, FPS] + +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 + } + +DICT_VIDEO_METADATA_L1 = { + CODEC: LIST_CASE_L2, + WIDTH: None, + HEIGHT: None, + LENGTH: None, + FPS: None, + ORDER_KEY: LIST_VIDEO_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, JOB_CODE] + +LIST_VIDEO_RENAME_L0 = LIST_IMAGE_RENAME_L0 + + +DICT_IMAGE_RENAME_L0 = { + DATE_TIME: DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_FILENAME_L1, + METADATA: DICT_METADATA_L1, + SEQUENCES: DICT_SEQUENCE_L1, + JOB_CODE: None, + ORDER_KEY: LIST_IMAGE_RENAME_L0 + } + +DICT_VIDEO_RENAME_L0 = { + DATE_TIME: VIDEO_DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_VIDEO_FILENAME_L1, + METADATA: DICT_VIDEO_METADATA_L1, + SEQUENCES: DICT_SEQUENCE_L1, + JOB_CODE: None, + ORDER_KEY: LIST_VIDEO_RENAME_L0 + } + +LIST_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, JOB_CODE, SEPARATOR] + +DICT_SUBFOLDER_L0 = { + DATE_TIME: DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_SUBFOLDER_FILENAME_L1, + METADATA: DICT_METADATA_L1, + JOB_CODE: None, + SEPARATOR: None, + ORDER_KEY: LIST_SUBFOLDER_L0 + } + +LIST_VIDEO_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, JOB_CODE, SEPARATOR] + +DICT_VIDEO_SUBFOLDER_L0 = { + DATE_TIME: VIDEO_DICT_DATE_TIME_L1, + TEXT: None, + FILENAME: DICT_SUBFOLDER_FILENAME_L1, + METADATA: DICT_VIDEO_METADATA_L1, + JOB_CODE: None, + SEPARATOR: None, + ORDER_KEY: LIST_VIDEO_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 diff --git a/rapid/glade3/about.ui b/rapid/glade3/about.ui new file mode 100644 index 0000000..ef8a65b --- /dev/null +++ b/rapid/glade3/about.ui @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="2.20"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkAboutDialog" id="about"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="destroy_with_parent">True</property> + <property name="icon">rapid-photo-downloader.svg</property> + <property name="type_hint">dialog</property> + <property name="program_name">Rapid Photo Downloader</property> + <property name="copyright">Copyright Damon Lynch 2007-11</property> + <property name="comments" translatable="yes">Import your photos and videos efficiently and reliably</property> + <property name="website">http://www.damonlynch.net/rapid</property> + <property name="license">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">Anton Alyab'ev <subeditor@dolgopa.org> +Lőrincz András <level.andrasnak@gmail.com> +Michel Ange <michelange@wanadoo.fr> +Alain J. Baudrez <a.baudrez@gmail.com> +Bert <crinbert@yahoo.com> +Martin Dahl Moe +Martin Egger <martin.egger@gmx.net> +Miroslav Matejaš <silverspace@ubuntu-hr.org> +Nicolás M. Zahlut <nzahlut@live.com> +Erik M +Jose Luis Navarro <jlnavarro111@gmail.com> +Tomas Novak <kuvaly@seznam.cz> +Abel O'Rian <abel.orian@gmail.com> +Balazs Oveges <ovegesb@freemail.hu> +Daniel Paessler <daniel@paessler.org> +Miloš Popović <gpopac@gmail.com> +Michal Predotka <mpredotka@googlemail.com> +Ye Qing <allen19920930@gmail.com> +Luca Reverberi <thereve@gmail.com> +Mikko Ruohola <polarfox@polarfox.net> +Sergiy Gavrylov <sergiovana@bigmir.net> +Sergei Sedov <sedov@webmail.perm.ru> +Marco Solari <marcosolari@gmail.com> +Toni Lähdekorpi <toni@lygon.net> +Ulf Urdén <ulf.urden@purplescout.com> +Julien Valroff <julien@kirya.net> +Aron Xu <happyaron.xu@gmail.com> +梁其学 <yalongbay@gmail.com></property> + <property name="logo">rapid-photo-downloader.svg</property> + <property name="wrap_license">True</property> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + </object> +</interface> diff --git a/rapid/glade3/errorlog.ui b/rapid/glade3/errorlog.ui new file mode 100644 index 0000000..43c8bdd --- /dev/null +++ b/rapid/glade3/errorlog.ui @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="2.20"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkDialog" id="errorlog"> + <property name="can_focus">False</property> + <property name="border_width">5</property> + <property name="title" translatable="yes">Error Log</property> + <property name="default_width">650</property> + <property name="default_height">400</property> + <property name="destroy_with_parent">True</property> + <property name="icon">rapid-photo-downloader.svg</property> + <property name="type_hint">dialog</property> + <signal name="response" handler="on_errorlog_response" swapped="no"/> + <child internal-child="vbox"> + <object class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkButton" id="button1"> + <property name="label">gtk-close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object 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> + <object class="GtkViewport" id="viewport1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkTextView" id="log_textview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="editable">False</property> + <property name="cursor_visible">False</property> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + </child> + <action-widgets> + <action-widget response="0">button1</action-widget> + </action-widgets> + </object> +</interface> diff --git a/rapid/glade3/media-eject.png b/rapid/glade3/media-eject.png Binary files differnew file mode 100644 index 0000000..0ff107e --- /dev/null +++ b/rapid/glade3/media-eject.png diff --git a/rapid/glade3/photo.png b/rapid/glade3/photo.png Binary files differdeleted file mode 100644 index b8bd550..0000000 --- a/rapid/glade3/photo.png +++ /dev/null diff --git a/rapid/glade3/photo.svg b/rapid/glade3/photo.svg new file mode 100644 index 0000000..95c57d0 --- /dev/null +++ b/rapid/glade3/photo.svg @@ -0,0 +1,1208 @@ +<?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://creativecommons.org/ns#" + 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" + version="1.0" + width="96" + height="96" + id="svg2408" + inkscape:version="0.48.1 r9760" + sodipodi:docname="camera-photo.svg" + inkscape:export-filename="/home/damon/rapid/branding/camera-photo.png" + inkscape:export-xdpi="69.209999" + inkscape:export-ydpi="69.209999"> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1920" + inkscape:window-height="1176" + id="namedview245" + showgrid="false" + inkscape:zoom="7.719249" + inkscape:cx="32.454446" + inkscape:cy="48" + inkscape:window-x="0" + inkscape:window-y="24" + inkscape:window-maximized="1" + inkscape:current-layer="svg2408" /> + <defs + id="defs2410"> + <linearGradient + id="linearGradient3921"> + <stop + id="stop3923" + style="stop-color:#5fd3bc;stop-opacity:0" + offset="0" /> + <stop + id="stop3929" + style="stop-color:#5fd3bc;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3925" + style="stop-color:#5fd3bc;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3911"> + <stop + id="stop3913" + style="stop-color:#2a7fff;stop-opacity:0" + offset="0" /> + <stop + id="stop3919" + style="stop-color:#2a7fff;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3915" + style="stop-color:#2a7fff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3901"> + <stop + id="stop3903" + style="stop-color:#6600ff;stop-opacity:0" + offset="0" /> + <stop + id="stop3909" + style="stop-color:#6600ff;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3905" + style="stop-color:#6600ff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3891"> + <stop + id="stop3893" + style="stop-color:#d42aff;stop-opacity:0" + offset="0" /> + <stop + id="stop3899" + style="stop-color:#d42aff;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3895" + style="stop-color:#d42aff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3881"> + <stop + id="stop3883" + style="stop-color:#d40000;stop-opacity:0" + offset="0" /> + <stop + id="stop3889" + style="stop-color:#d40000;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3885" + style="stop-color:#d40000;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3871"> + <stop + id="stop3873" + style="stop-color:#ff6600;stop-opacity:0" + offset="0" /> + <stop + id="stop3879" + style="stop-color:#ff6600;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3875" + style="stop-color:#ff6600;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3861"> + <stop + id="stop3863" + style="stop-color:#ffcc00;stop-opacity:0" + offset="0" /> + <stop + id="stop3869" + style="stop-color:#ffcc00;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3865" + style="stop-color:#ffcc00;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3851"> + <stop + id="stop3853" + style="stop-color:#55d400;stop-opacity:0" + offset="0" /> + <stop + id="stop3859" + style="stop-color:#55d400;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3855" + style="stop-color:#55d400;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3797"> + <stop + id="stop3799" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3805" + style="stop-color:#ffffff;stop-opacity:1" + offset="0.5" /> + <stop + id="stop3801" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3761"> + <stop + id="stop3763" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3765" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3727"> + <stop + id="stop3729" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3731" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3681"> + <stop + id="stop3683" + style="stop-color:#ffffff;stop-opacity:0.18548387" + offset="0" /> + <stop + id="stop3689" + style="stop-color:#ffffff;stop-opacity:0.10887097" + offset="0.3086735" /> + <stop + id="stop3691" + style="stop-color:#000000;stop-opacity:0" + offset="0.43622452" /> + <stop + id="stop3693" + style="stop-color:#000000;stop-opacity:0" + offset="0.54464293" /> + <stop + id="stop3695" + style="stop-color:#ffffff;stop-opacity:0" + offset="0.58290821" /> + <stop + id="stop3697" + style="stop-color:#000000;stop-opacity:0.1814516" + offset="0.61479598" /> + <stop + id="stop3699" + style="stop-color:#000000;stop-opacity:0.43145162" + offset="0.69132656" /> + <stop + id="stop3701" + style="stop-color:#ffffff;stop-opacity:0.08064516" + offset="0.78061229" /> + <stop + id="stop3703" + style="stop-color:#000000;stop-opacity:0" + offset="0.87627554" /> + <stop + id="stop3685" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3746"> + <stop + id="stop3748" + style="stop-color:#5d5d5d;stop-opacity:1" + offset="0" /> + <stop + id="stop3753" + style="stop-color:#0a0a0a;stop-opacity:1" + offset="0.60000002" /> + <stop + id="stop3751" + style="stop-color:#4e4e4e;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3732"> + <stop + id="stop3734" + style="stop-color:#000000;stop-opacity:0" + offset="0" /> + <stop + id="stop3740" + style="stop-color:#000000;stop-opacity:0" + offset="0.94999999" /> + <stop + id="stop3736" + style="stop-color:#000000;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3719"> + <stop + id="stop3721" + style="stop-color:#4b4b4b;stop-opacity:1" + offset="0" /> + <stop + id="stop3723" + style="stop-color:#232323;stop-opacity:1" + offset="0.37373093" /> + <stop + id="stop3725" + style="stop-color:#5c5c5c;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3664"> + <stop + id="stop3666" + style="stop-color:#000000;stop-opacity:0.68992245" + offset="0" /> + <stop + id="stop3804" + style="stop-color:#7f7f7f;stop-opacity:0" + offset="0.5" /> + <stop + id="stop3668" + style="stop-color:#ffffff;stop-opacity:0.21705426" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3650"> + <stop + id="stop3709" + style="stop-color:#141414;stop-opacity:1" + offset="0" /> + <stop + id="stop3654" + style="stop-color:#616161;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3641"> + <stop + id="stop3643" + style="stop-color:#0c0c0c;stop-opacity:1" + offset="0" /> + <stop + id="stop3645" + style="stop-color:#373737;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + x1="45.447727" + y1="92.539597" + x2="45.447727" + y2="7.0165396" + id="ButtonShadow" + gradientUnits="userSpaceOnUse" + gradientTransform="scale(1.0058652,0.994169)"> + <stop + id="stop3750" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3752" + style="stop-color:#000000;stop-opacity:0.58823532" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3737"> + <stop + id="stop3739" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3741" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <filter + color-interpolation-filters="sRGB" + id="filter3174"> + <feGaussianBlur + id="feGaussianBlur3176" + stdDeviation="1.71" /> + </filter> + <linearGradient + x1="36.357143" + y1="6" + x2="36.357143" + y2="63.893143" + id="linearGradient3188" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" /> + <filter + x="-0.192" + y="-0.192" + width="1.3839999" + height="1.3839999" + color-interpolation-filters="sRGB" + id="filter3794"> + <feGaussianBlur + id="feGaussianBlur3796" + stdDeviation="5.28" /> + </filter> + <linearGradient + x1="48" + y1="20.220806" + x2="48" + y2="138.66119" + id="linearGradient3613" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="48" + cy="90.171875" + r="42" + fx="48" + fy="90.171875" + id="radialGradient3619" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.1573129,0,0,0.99590774,-7.5510206,0.19713193)" /> + <clipPath + id="clipPath3613"> + <rect + width="84" + height="84" + rx="6" + ry="6" + x="6" + y="6" + id="rect3615" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </clipPath> + <linearGradient + x1="48" + y1="90" + x2="48" + y2="5.9877172" + id="linearGradient3617" + xlink:href="#linearGradient3641" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="16.162441" + y1="52.098946" + x2="76.838295" + y2="52.098946" + id="linearGradient3670" + xlink:href="#linearGradient3664" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="16.162441" + y1="44.48222" + x2="76.771591" + y2="44.48222" + id="linearGradient3674" + xlink:href="#linearGradient3719" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="16.162441" + y1="44.48222" + x2="76.771591" + y2="44.48222" + id="linearGradient3707" + xlink:href="#linearGradient3650" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="48" + cy="48.000935" + r="27.001867" + fx="48" + fy="48.000935" + id="radialGradient3738" + xlink:href="#linearGradient3732" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0369653,0,0,1.0369653,-1.774336,-1.7753043)" /> + <linearGradient + x1="16.162441" + y1="44.48222" + x2="76.771591" + y2="44.48222" + id="linearGradient3744" + xlink:href="#linearGradient3746" + gradientUnits="userSpaceOnUse" /> + <clipPath + id="clipPath3798"> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 1 1 -27.274118,0 13.637059,13.637059 0 1 1 27.274118,0 z" + transform="matrix(1.0266143,0,0,1.0266143,-0.999999,0.778362)" + id="path3800" + style="fill:#ff00ff;fill-opacity:1;stroke:none" /> + </clipPath> + <filter + x="-0.23999999" + y="-0.24000001" + width="1.48" + height="1.48" + color-interpolation-filters="sRGB" + id="filter3833"> + <feGaussianBlur + id="feGaussianBlur3835" + stdDeviation="2.8000002" /> + </filter> + <radialGradient + cx="47.729706" + cy="45.997448" + r="13.637059" + fx="47.729706" + fy="45.997448" + id="radialGradient3687" + xlink:href="#linearGradient3681" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="33.199345" + y1="45.997448" + x2="67.957489" + y2="45.997448" + id="linearGradient3733" + xlink:href="#linearGradient3727" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="40.068184" + y1="58.17598" + x2="31.793724" + y2="49.665066" + id="linearGradient3767" + xlink:href="#linearGradient3761" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="40.068184" + y1="58.17598" + x2="40.068184" + y2="41.697067" + id="linearGradient3771" + xlink:href="#linearGradient3761" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="40.068184" + y1="58.17598" + x2="40.068184" + y2="41.697067" + id="linearGradient3775" + xlink:href="#linearGradient3761" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="40.068184" + y1="58.17598" + x2="40.068184" + y2="41.697067" + id="linearGradient3779" + xlink:href="#linearGradient3761" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="40.068184" + y1="58.17598" + x2="40.068184" + y2="41.697067" + id="linearGradient3791" + xlink:href="#linearGradient3761" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="41" + cy="52" + r="9.7082043" + fx="41" + fy="52" + id="radialGradient3803" + xlink:href="#linearGradient3797" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,0.61803397,0,19.862234)" /> + <filter + color-interpolation-filters="sRGB" + id="filter3774"> + <feGaussianBlur + id="feGaussianBlur3776" + stdDeviation="0.27274118" /> + </filter> + <linearGradient + x1="53.510502" + y1="59.608364" + x2="61.49099" + y2="39.92907" + id="linearGradient3967" + xlink:href="#linearGradient3881" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0266143,0,0,1.0266143,-0.9999987,50.778362)" /> + <linearGradient + x1="53.730709" + y1="60.139374" + x2="62.58559" + y2="38.831467" + id="linearGradient3969" + xlink:href="#linearGradient3891" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.72592593,0.72592593,-0.72592593,0.72592593,46.742509,29.961028)" /> + <linearGradient + x1="53.387505" + y1="60.34634" + x2="61.982975" + y2="39.437084" + id="linearGradient3971" + xlink:href="#linearGradient3901" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0,1.0266143,-1.0266143,0,95.221638,49.000001)" /> + <linearGradient + x1="53.295853" + y1="59.182693" + x2="61.88982" + y2="40.223007" + id="linearGradient3973" + xlink:href="#linearGradient3911" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.72592593,0.72592593,-0.72592593,-0.72592593,116.03897,96.742509)" /> + <linearGradient + x1="53.87949" + y1="61.330303" + x2="60.999012" + y2="39.683075" + id="linearGradient3975" + xlink:href="#linearGradient3921" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-1.0266143,0,0,-1.0266143,96.999997,145.22164)" /> + <linearGradient + x1="53.469795" + y1="59.878456" + x2="60.324341" + y2="39.70118" + id="linearGradient3977" + xlink:href="#linearGradient3851" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(-0.72592593,-0.72592593,0.72592593,-0.72592593,49.25749,166.03897)" /> + <linearGradient + x1="61.628212" + y1="39.683075" + x2="52.881298" + y2="60.715324" + id="linearGradient3979" + xlink:href="#linearGradient3861" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0,-1.0266143,1.0266143,0,0.77836254,147)" /> + <linearGradient + x1="53.034939" + y1="61.183025" + x2="61.802849" + y2="40.483921" + id="linearGradient3981" + xlink:href="#linearGradient3871" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.72592593,-0.72592593,0.72592593,0.72592593,-20.03897,99.25749)" /> + <filter + color-interpolation-filters="sRGB" + id="filter3987"> + <feGaussianBlur + id="feGaussianBlur3989" + stdDeviation="0.42020394" /> + </filter> + <linearGradient + x1="64.072342" + y1="64.036171" + x2="46.604744" + y2="46.568573" + id="linearGradient3817" + xlink:href="#linearGradient3761" + gradientUnits="userSpaceOnUse" /> + <linearGradient + x1="45.447727" + y1="92.539597" + x2="45.447727" + y2="7.0165396" + id="ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0058652,0,0,0.994169,100,0)"> + <stop + id="stop3750-8" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3752-5" + style="stop-color:#000000;stop-opacity:0.58823532" + offset="1" /> + </linearGradient> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3780" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3772" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3725" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3721" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,-97)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient2918" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="15.999999" + y1="85.0625" + x2="20.178572" + y2="85.0625" + id="linearGradient3556" + xlink:href="#linearGradient3376" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3376"> + <stop + id="stop3378" + style="stop-color:#767676;stop-opacity:1" + offset="0" /> + <stop + id="stop3380" + style="stop-color:#fdfdfd;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3733-2"> + <stop + id="stop3735" + style="stop-color:#ffbf67;stop-opacity:1" + offset="0" /> + <stop + id="stop3737" + style="stop-color:#c70000;stop-opacity:1" + offset="1" /> + </linearGradient> + <radialGradient + cx="18.089285" + cy="85.0625" + r="2.0892856" + fx="18.089285" + fy="85.0625" + id="radialGradient3029" + xlink:href="#linearGradient3733-2" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.0042736,0,-0.3635233)" /> + </defs> + <metadata + id="metadata2413"> + <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 /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer2" + style="display:none"> + <rect + width="86" + height="85" + rx="6" + ry="6" + x="5" + y="7" + id="rect3745" + style="opacity:0.9;fill:url(#ButtonShadow);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3174)" /> + </g> + <g + id="layer1" + style="display:inline" + inkscape:export-xdpi="70.709999" + inkscape:export-ydpi="70.709999" + inkscape:export-filename="/home/damon/rapid/branding/photo66.png"> + <rect + width="84" + height="84" + rx="6" + ry="6" + x="6" + y="6" + id="rect2419" + style="fill:url(#linearGradient3617);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 12,6 C 8.676,6 6,8.676 6,12 l 0,2 0,68 0,2 c 0,0.334721 0.04135,0.6507 0.09375,0.96875 0.0487,0.295596 0.09704,0.596915 0.1875,0.875 0.00988,0.03038 0.020892,0.0636 0.03125,0.09375 0.098865,0.287771 0.2348802,0.547452 0.375,0.8125 0.1445918,0.273507 0.3156161,0.535615 0.5,0.78125 0.1843839,0.245635 0.3737765,0.473472 0.59375,0.6875 0.439947,0.428056 0.94291,0.814526 1.5,1.09375 0.278545,0.139612 0.5734731,0.246947 0.875,0.34375 -0.2562018,-0.100222 -0.4867109,-0.236272 -0.71875,-0.375 -0.00741,-0.0044 -0.023866,0.0045 -0.03125,0 -0.031933,-0.0193 -0.062293,-0.04251 -0.09375,-0.0625 -0.120395,-0.0767 -0.2310226,-0.163513 -0.34375,-0.25 -0.1061728,-0.0808 -0.2132809,-0.161112 -0.3125,-0.25 C 8.4783201,88.557317 8.3087904,88.373362 8.15625,88.1875 8.0486711,88.057245 7.9378561,87.922215 7.84375,87.78125 7.818661,87.74287 7.805304,87.69538 7.78125,87.65625 7.716487,87.553218 7.6510225,87.451733 7.59375,87.34375 7.4927417,87.149044 7.3880752,86.928049 7.3125,86.71875 7.30454,86.69694 7.288911,86.6782 7.28125,86.65625 7.2494249,86.5643 7.2454455,86.469419 7.21875,86.375 7.1884177,86.268382 7.1483606,86.171969 7.125,86.0625 7.0521214,85.720988 7,85.364295 7,85 L 7,83 7,15 7,13 C 7,10.218152 9.2181517,8 12,8 l 2,0 68,0 2,0 c 2.781848,0 5,2.218152 5,5 l 0,2 0,68 0,2 c 0,0.364295 -0.05212,0.720988 -0.125,1.0625 -0.04415,0.206893 -0.08838,0.397658 -0.15625,0.59375 -0.0077,0.02195 -0.0233,0.04069 -0.03125,0.0625 -0.06274,0.173739 -0.138383,0.367449 -0.21875,0.53125 -0.04158,0.0828 -0.07904,0.169954 -0.125,0.25 -0.0546,0.09721 -0.126774,0.18835 -0.1875,0.28125 -0.09411,0.140965 -0.204921,0.275995 -0.3125,0.40625 -0.143174,0.17445 -0.303141,0.346998 -0.46875,0.5 -0.01117,0.0102 -0.01998,0.02115 -0.03125,0.03125 -0.138386,0.125556 -0.285091,0.234436 -0.4375,0.34375 -0.102571,0.07315 -0.204318,0.153364 -0.3125,0.21875 -0.0074,0.0045 -0.02384,-0.0044 -0.03125,0 -0.232039,0.138728 -0.462548,0.274778 -0.71875,0.375 0.301527,-0.0968 0.596455,-0.204138 0.875,-0.34375 0.55709,-0.279224 1.060053,-0.665694 1.5,-1.09375 0.219973,-0.214028 0.409366,-0.441865 0.59375,-0.6875 0.184384,-0.245635 0.355408,-0.507743 0.5,-0.78125 0.14012,-0.265048 0.276135,-0.524729 0.375,-0.8125 0.01041,-0.03078 0.02133,-0.06274 0.03125,-0.09375 0.09046,-0.278085 0.1388,-0.579404 0.1875,-0.875 C 89.95865,84.6507 90,84.334721 90,84 l 0,-2 0,-68 0,-2 C 90,8.676 87.324,6 84,6 L 12,6 z" + inkscape:connector-curvature="0" + id="rect3728" + style="opacity:0.25;fill:url(#linearGradient3188);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="M 12,90 C 8.676,90 6,87.324 6,84 L 6,82 6,14 6,12 c 0,-0.334721 0.04135,-0.6507 0.09375,-0.96875 0.0487,-0.295596 0.09704,-0.596915 0.1875,-0.875 C 6.29113,10.12587 6.302142,10.09265 6.3125,10.0625 6.411365,9.774729 6.5473802,9.515048 6.6875,9.25 6.8320918,8.976493 7.0031161,8.714385 7.1875,8.46875 7.3718839,8.223115 7.5612765,7.995278 7.78125,7.78125 8.221197,7.353194 8.72416,6.966724 9.28125,6.6875 9.559795,6.547888 9.8547231,6.440553 10.15625,6.34375 9.9000482,6.443972 9.6695391,6.580022 9.4375,6.71875 c -0.00741,0.0044 -0.023866,-0.0045 -0.03125,0 -0.031933,0.0193 -0.062293,0.04251 -0.09375,0.0625 -0.120395,0.0767 -0.2310226,0.163513 -0.34375,0.25 -0.1061728,0.0808 -0.2132809,0.161112 -0.3125,0.25 C 8.4783201,7.442683 8.3087904,7.626638 8.15625,7.8125 8.0486711,7.942755 7.9378561,8.077785 7.84375,8.21875 7.818661,8.25713 7.805304,8.30462 7.78125,8.34375 7.716487,8.446782 7.6510225,8.548267 7.59375,8.65625 7.4927417,8.850956 7.3880752,9.071951 7.3125,9.28125 7.30454,9.30306 7.288911,9.3218 7.28125,9.34375 7.2494249,9.4357 7.2454455,9.530581 7.21875,9.625 7.1884177,9.731618 7.1483606,9.828031 7.125,9.9375 7.0521214,10.279012 7,10.635705 7,11 l 0,2 0,68 0,2 c 0,2.781848 2.2181517,5 5,5 l 2,0 68,0 2,0 c 2.781848,0 5,-2.218152 5,-5 l 0,-2 0,-68 0,-2 C 89,10.635705 88.94788,10.279012 88.875,9.9375 88.83085,9.730607 88.78662,9.539842 88.71875,9.34375 88.71105,9.3218 88.69545,9.30306 88.6875,9.28125 88.62476,9.107511 88.549117,8.913801 88.46875,8.75 88.42717,8.6672 88.38971,8.580046 88.34375,8.5 88.28915,8.40279 88.216976,8.31165 88.15625,8.21875 88.06214,8.077785 87.951329,7.942755 87.84375,7.8125 87.700576,7.63805 87.540609,7.465502 87.375,7.3125 87.36383,7.3023 87.35502,7.29135 87.34375,7.28125 87.205364,7.155694 87.058659,7.046814 86.90625,6.9375 86.803679,6.86435 86.701932,6.784136 86.59375,6.71875 c -0.0074,-0.0045 -0.02384,0.0044 -0.03125,0 -0.232039,-0.138728 -0.462548,-0.274778 -0.71875,-0.375 0.301527,0.0968 0.596455,0.204138 0.875,0.34375 0.55709,0.279224 1.060053,0.665694 1.5,1.09375 0.219973,0.214028 0.409366,0.441865 0.59375,0.6875 0.184384,0.245635 0.355408,0.507743 0.5,0.78125 0.14012,0.265048 0.276135,0.524729 0.375,0.8125 0.01041,0.03078 0.02133,0.06274 0.03125,0.09375 0.09046,0.278085 0.1388,0.579404 0.1875,0.875 C 89.95865,11.3493 90,11.665279 90,12 l 0,2 0,68 0,2 c 0,3.324 -2.676,6 -6,6 l -72,0 z" + inkscape:connector-curvature="0" + id="path3615" + style="opacity:0.15;fill:url(#radialGradient3619);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + id="layer5" + style="display:none"> + <rect + width="66" + height="66" + rx="12" + ry="12" + x="15" + y="15" + clip-path="url(#clipPath3613)" + id="rect3171" + style="opacity:0.5;fill:url(#linearGradient3613);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3794)" /> + </g> + <g + id="layer3"> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,1.1879394,-1.1879394,0,100.84218,-7.2000033)" + id="path3660" + style="fill:url(#linearGradient3670);fill-opacity:1;stroke:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0.79333332,0.79333332,-0.79333332,0.79333332,46.425393,-24.15306)" + id="path3648" + style="fill:url(#linearGradient3674);fill-opacity:1;stroke:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,1.1136932,-1.1136932,0,97.53954,-3.75)" + id="path3672" + style="fill:none;stroke:#000000;stroke-width:0.44895676;stroke-miterlimit:4;stroke-dasharray:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,0.92395284,-0.92395284,0,89.099473,5.0666664)" + id="path3697" + style="fill:url(#linearGradient3707);fill-opacity:1;stroke:none" /> + <g + transform="matrix(0.92592592,0,0,0.92592592,3.555556,3.5555557)" + id="g3691" + style="opacity:0.2"> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,0.88270495,-0.88270495,0,87.264675,6.9833334)" + id="path3676" + style="fill:none;stroke:#000000;stroke-width:0.61175603;stroke-miterlimit:4;stroke-dasharray:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,0.81670832,-0.81670832,0,84.328998,10.05)" + id="path3678" + style="fill:none;stroke:#000000;stroke-width:0.66119081;stroke-miterlimit:4;stroke-dasharray:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,0.84970663,-0.84970663,0,85.796836,8.5166669)" + id="path3680" + style="fill:none;stroke:#000000;stroke-width:0.63551354;stroke-miterlimit:4;stroke-dasharray:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,0.78371,-0.78371,0,82.861159,11.583334)" + id="path3682" + style="fill:none;stroke:#000000;stroke-width:0.68903041;stroke-miterlimit:4;stroke-dasharray:none" /> + </g> + <path + d="m 48,20 c -7.16533,0 -14.332595,2.731639 -19.799557,8.19879 -10.933924,10.934302 -10.933924,28.666181 0,39.600483 10.933924,10.934303 28.66519,10.934303 39.599114,0 10.933924,-10.934302 10.933924,-28.666181 0,-39.600483 C 62.332595,22.731639 55.16533,20 48,20 z m 0,2.592503 c 6.501873,0 12.9917,2.492512 17.952462,7.453446 9.921524,9.921866 9.921524,25.9843 0,35.906166 -9.921523,9.921867 -25.983401,9.921867 -35.904924,0 -9.921524,-9.921866 -9.921524,-25.9843 0,-35.906166 C 35.0083,25.085015 41.498127,22.592503 48,22.592503 z" + inkscape:connector-curvature="0" + id="path3727" + style="opacity:0.6;fill:url(#radialGradient3738);fill-opacity:1;stroke:none" /> + <path + d="m 76.771595,44.48222 a 30.304577,30.304577 0 1 1 -60.609154,0 30.304577,30.304577 0 1 1 60.609154,0 z" + transform="matrix(0,0.64907743,-0.64907743,0,76.872405,17.839307)" + id="path3742" + style="fill:url(#linearGradient3744);fill-opacity:1;stroke:#1a1a1a;stroke-width:1.54064822;stroke-miterlimit:4;stroke-dasharray:none" /> + <path + d="m 20.178571,85.0625 a 2.0892856,2.0982144 0 1 1 -4.178572,0 2.0892856,2.0982144 0 1 1 4.178572,0 z" + transform="matrix(0,1.6709402,1.6638297,0,-126.03844,-14.717185)" + id="path3374" + style="opacity:0.4025974;fill:url(#linearGradient3556);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 20.178571,85.0625 a 2.0892856,2.0982144 0 1 1 -4.178572,0 2.0892856,2.0982144 0 1 1 4.178572,0 z" + transform="matrix(1.1923077,0,0,1.1872339,-6.0769275,-85.480158)" + id="path3364" + style="fill:url(#radialGradient3029);fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.84049988;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:0.53181823;stroke-dasharray:none;stroke-dashoffset:0" /> + <g + transform="matrix(-0.5,0.8660254,-0.8660254,-0.5,113.57328,30.437809)" + id="text3845" + style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.70995669;fill:#b3b3b3;fill-opacity:1;stroke:none;font-family:Liberation Sans;-inkscape-font-specification:Liberation Sans"> + <path + d="m 45.682364,77.430433 2.189583,0.08937 -0.01139,0.279065 -1.7628,2.097825 1.531928,0.06253 -0.01243,0.304434 -1.955403,-0.07981 0.01107,-0.271258 1.763118,-2.105631 -1.766108,-0.07208 0.01243,-0.304434" + inkscape:connector-curvature="0" + id="path3853" /> + <path + d="m 42.472517,78.425885 c 0.02879,-0.212908 0.08593,-0.402272 0.171412,-0.568093 0.0842,-0.165997 0.19274,-0.303081 0.325617,-0.411252 0.132881,-0.108172 0.287729,-0.184466 0.464543,-0.228884 0.176819,-0.04442 0.37168,-0.05223 0.584585,-0.02345 0.224521,0.03036 0.416587,0.0918 0.5762,0.184334 0.159441,0.09382 0.286829,0.210906 0.382165,0.351247 0.09516,0.141631 0.159443,0.302738 0.19284,0.483321 0.0334,0.180581 0.03623,0.373454 0.0085,0.57862 -0.02879,0.212905 -0.08446,0.401153 -0.167018,0.564745 -0.08256,0.163589 -0.189371,0.297621 -0.320437,0.402098 -0.131239,0.105763 -0.285092,0.179564 -0.461561,0.221404 -0.177931,0.04295 -0.375931,0.04968 -0.594001,0.0202 -0.216775,-0.02931 -0.404587,-0.08821 -0.563437,-0.176695 -0.160134,-0.08866 -0.288778,-0.201318 -0.385932,-0.33796 -0.09844,-0.136822 -0.165735,-0.295051 -0.20189,-0.47469 -0.03615,-0.179643 -0.04001,-0.374626 -0.01157,-0.58495 m 0.377425,0.05103 c -0.02215,0.163872 -0.02101,0.315785 0.0034,0.455739 0.02315,0.139777 0.06956,0.262991 0.139229,0.369644 0.06838,0.106475 0.159731,0.193719 0.274042,0.261734 0.114316,0.06801 0.250829,0.112747 0.409539,0.134208 0.162585,0.02198 0.308657,0.01545 0.438217,-0.01959 0.129562,-0.03504 0.242088,-0.09472 0.337579,-0.179039 0.0942,-0.0845 0.171021,-0.19105 0.230455,-0.319661 0.05815,-0.128789 0.0983,-0.275119 0.120452,-0.438991 0.02216,-0.163875 0.02184,-0.316991 -9.62e-4,-0.459349 -0.02426,-0.141244 -0.07032,-0.267039 -0.138182,-0.377386 -0.06932,-0.109232 -0.160878,-0.19979 -0.274669,-0.271674 -0.115254,-0.07077 -0.252238,-0.116881 -0.410951,-0.13834 -0.170324,-0.02303 -0.320529,-0.01509 -0.450615,0.02382 -0.131372,0.03874 -0.243045,0.101816 -0.335017,0.18924 -0.09343,0.08854 -0.168106,0.198668 -0.224021,0.330386 -0.0572,0.131541 -0.09671,0.277959 -0.118517,0.439253" + inkscape:connector-curvature="0" + id="path3855" /> + <path + d="m 39.301436,77.678216 c 0.05112,-0.208676 0.127935,-0.390946 0.230457,-0.546811 0.101263,-0.156174 0.223674,-0.281027 0.367232,-0.374559 0.143564,-0.09353 0.305604,-0.153043 0.48612,-0.178537 0.180521,-0.02549 0.375118,-0.01268 0.583792,0.03843 0.220058,0.0539 0.404561,0.135289 0.553507,0.244163 0.148639,0.110139 0.262948,0.240021 0.342928,0.389647 0.07967,0.150891 0.126575,0.317886 0.140711,0.500986 0.01414,0.183099 -0.0034,0.375192 -0.05268,0.57628 -0.05111,0.208673 -0.126357,0.389988 -0.225734,0.543945 -0.09938,0.153953 -0.219747,0.275954 -0.361115,0.366003 -0.141676,0.09131 -0.302464,0.148447 -0.482364,0.171414 -0.181473,0.02392 -0.379076,0.0097 -0.592812,-0.04265 -0.212467,-0.05205 -0.393008,-0.130451 -0.541622,-0.235219 -0.149874,-0.105082 -0.2659,-0.230693 -0.348077,-0.376833 -0.08344,-0.146453 -0.133644,-0.310906 -0.150623,-0.493359 -0.01697,-0.182456 -2.14e-4,-0.376756 0.05028,-0.5829 m 0.369924,0.09061 c -0.03934,0.160615 -0.05425,0.311799 -0.04474,0.453551 0.0083,0.14144 0.04139,0.268868 0.09941,0.382282 0.05676,0.113102 0.138377,0.209507 0.244865,0.289216 0.106493,0.0797 0.237517,0.138609 0.393072,0.176713 0.159354,0.03903 0.305298,0.04797 0.437834,0.02681 0.132539,-0.02116 0.250739,-0.06862 0.354602,-0.142382 0.1026,-0.07407 0.190243,-0.171917 0.262929,-0.293531 0.07142,-0.121927 0.126805,-0.263198 0.166146,-0.423814 0.03934,-0.160617 0.0552,-0.312911 0.04756,-0.456881 -0.0092,-0.143016 -0.04172,-0.272973 -0.09755,-0.38987 -0.0574,-0.115943 -0.138876,-0.215664 -0.244439,-0.299165 -0.107134,-0.08255 -0.238481,-0.14287 -0.39404,-0.180972 -0.166938,-0.04089 -0.317142,-0.04886 -0.45061,-0.02391 -0.134729,0.02464 -0.25244,0.07558 -0.353131,0.152797 -0.102262,0.07818 -0.18815,0.1798 -0.257665,0.304875 -0.07077,0.124764 -0.125524,0.26619 -0.164248,0.424278" + inkscape:connector-curvature="0" + id="path3857" /> + <path + d="m 36.93709,75.37391 -0.630016,1.724455 c -0.02278,0.06237 -0.04663,0.125747 -0.07154,0.190121 -0.0249,0.06437 -0.04841,0.123018 -0.07052,0.175938 -0.02523,0.06148 -0.05041,0.120902 -0.07552,0.178268 0.03991,-0.05612 0.08021,-0.111404 0.120894,-0.165851 0.03512,-0.04678 0.0734,-0.09656 0.114863,-0.14934 0.03979,-0.052 0.07758,-0.0985 0.113345,-0.139497 l 1.311189,-1.517182 0.245826,0.08981 0.03352,2.00846 c 6.37e-4,0.02103 7.68e-4,0.04533 3.91e-4,0.07292 -0.0016,0.02714 -0.0024,0.05595 -0.0025,0.08643 -0.0017,0.03126 -0.0028,0.06274 -0.0033,0.09444 -0.0022,0.03248 -0.0041,0.06435 -0.0058,0.09561 -0.0029,0.07241 -0.0073,0.147052 -0.01319,0.223915 0.0238,-0.06894 0.04676,-0.137485 0.06889,-0.205643 0.01856,-0.05838 0.03884,-0.119587 0.06085,-0.183629 0.02157,-0.06282 0.04106,-0.118081 0.05849,-0.165777 l 0.630016,-1.724456 0.31187,0.113939 -0.944354,2.584849 -0.460466,-0.168228 -0.03313,-2.043669 c 3.78e-4,-0.02759 0.0016,-0.06319 0.0037,-0.106789 0.0016,-0.04238 0.0043,-0.08576 0.008,-0.130144 0.0037,-0.04438 0.008,-0.08648 0.01287,-0.126299 0.0032,-0.03904 0.0065,-0.06902 0.01,-0.08993 -0.01082,0.01823 -0.02782,0.0439 -0.05101,0.07702 -0.02319,0.03312 -0.04827,0.06762 -0.07525,0.103511 -0.0282,0.03545 -0.05534,0.06989 -0.08142,0.103335 -0.02608,0.03345 -0.04848,0.06061 -0.0672,0.0815 l -1.32992,1.545688 -0.449459,-0.164206 0.944354,-2.584848 0.315538,0.115279" + inkscape:connector-curvature="0" + id="path3859" /> + <path + d="m 35.016377,74.508208 -1.277834,2.43729 -0.330392,-0.173219 1.136356,-2.167442 -1.231619,-0.645719 0.141478,-0.269849 1.562011,0.818939" + inkscape:connector-curvature="0" + id="path3861" /> + <path + d="m 33.052264,73.45796 -1.475751,2.322801 -1.762295,-1.119644 0.16339,-0.257173 1.447423,0.919595 0.473414,-0.745142 -1.348511,-0.856753 0.161296,-0.253876 1.34851,0.856752 0.514261,-0.809436 -1.515013,-0.962537 0.16339,-0.257173 1.829886,1.162586" + inkscape:connector-curvature="0" + id="path3863" /> + <path + d="m 29.39996,70.908274 -0.273684,2.754447 c 0.03706,-0.052 0.07321,-0.103884 0.108446,-0.155651 0.03068,-0.04377 0.06386,-0.08971 0.09956,-0.137827 0.03387,-0.04788 0.06478,-0.08983 0.09272,-0.125828 l 1.120895,-1.444173 0.262296,0.203582 -1.687331,2.173973 -0.342528,-0.265853 0.270922,-2.776371 c -0.03603,0.0528 -0.07207,0.105595 -0.108102,0.158391 -0.03147,0.0448 -0.06574,0.0932 -0.102804,0.145196 -0.03786,0.05303 -0.07475,0.102686 -0.11068,0.148973 l -1.106525,1.425657 -0.265382,-0.205977 1.687331,-2.173973 0.354871,0.275434" + inkscape:connector-curvature="0" + id="path3865" /> + <path + d="m 26.456345,69.279934 c 0.07932,-0.08449 0.169006,-0.146739 0.269069,-0.186749 0.09912,-0.0409 0.207358,-0.05537 0.324723,-0.04342 0.116476,0.0129 0.24074,0.05365 0.372792,0.122251 0.130213,0.06866 0.266519,0.169826 0.408917,0.303501 0.249675,0.23438 0.403294,0.46074 0.460857,0.67908 0.05756,0.218341 0.0278,0.427927 -0.08929,0.628758 L 27.890512,70.58874 c 0.03572,-0.06469 0.05987,-0.131317 0.07244,-0.199881 0.01257,-0.06856 0.01031,-0.140343 -0.0068,-0.215339 -0.01895,-0.07494 -0.05505,-0.153477 -0.108314,-0.235621 -0.05326,-0.08214 -0.128304,-0.168665 -0.225137,-0.259566 -0.08069,-0.07575 -0.160978,-0.138615 -0.240858,-0.188599 -0.08077,-0.04903 -0.158729,-0.08203 -0.233882,-0.09901 -0.07515,-0.01697 -0.146958,-0.01562 -0.215426,0.004 -0.07031,0.01972 -0.134868,0.06091 -0.193687,0.12357 -0.06149,0.06551 -0.09621,0.132926 -0.10415,0.202264 -0.0089,0.06845 0.0012,0.141361 0.0304,0.218739 0.02916,0.07738 0.07277,0.160287 0.130836,0.248727 0.05807,0.08844 0.122864,0.185879 0.194392,0.292317 0.04443,0.06492 0.08843,0.131236 0.132026,0.198947 0.04175,0.06777 0.07938,0.136128 0.112875,0.205079 0.03166,0.06901 0.05735,0.138666 0.07707,0.208973 0.01973,0.07031 0.02838,0.140042 0.02595,0.209207 -0.0033,0.07011 -0.01909,0.139239 -0.04734,0.207378 -0.02914,0.06909 -0.0749,0.136856 -0.137279,0.20331 -0.08912,0.09493 -0.184298,0.158276 -0.285546,0.190033 -0.103085,0.03181 -0.209301,0.03747 -0.318649,0.01698 -0.109344,-0.0205 -0.219891,-0.06444 -0.331643,-0.131842 -0.111746,-0.0674 -0.221732,-0.151897 -0.329959,-0.25349 -0.124359,-0.116745 -0.221327,-0.226524 -0.290903,-0.329339 -0.07046,-0.101866 -0.117802,-0.200778 -0.142025,-0.296735 -0.02421,-0.09596 -0.02718,-0.189824 -0.0089,-0.281597 0.01645,-0.09172 0.0494,-0.185796 0.09886,-0.282239 l 0.311825,0.204319 c -0.03216,0.06089 -0.05324,0.122356 -0.06326,0.184391 -0.01096,0.06114 -0.0081,0.123692 0.0087,0.187645 0.01676,0.06395 0.04833,0.130199 0.09471,0.198743 0.04544,0.06765 0.107549,0.138462 0.186341,0.21243 0.09304,0.08733 0.179377,0.152312 0.259021,0.194934 0.07781,0.04268 0.14954,0.06805 0.215195,0.07611 0.06471,0.0072 0.123878,-6.92e-4 0.177502,-0.02357 0.05179,-0.02282 0.09862,-0.05654 0.140506,-0.101162 0.05615,-0.05981 0.08777,-0.122988 0.09488,-0.189536 0.0053,-0.06649 -0.0057,-0.136614 -0.0329,-0.210369 -0.0272,-0.07376 -0.06648,-0.150814 -0.117845,-0.231175 -0.05136,-0.08036 -0.106992,-0.164733 -0.1669,-0.253115 -0.04834,-0.07217 -0.09576,-0.144362 -0.142256,-0.216586 -0.04834,-0.07217 -0.09071,-0.144982 -0.127115,-0.218447 -0.03729,-0.07251 -0.06723,-0.145262 -0.0898,-0.218243 -0.02352,-0.07387 -0.0346,-0.147675 -0.03325,-0.221412 0.0014,-0.07374 0.01747,-0.147018 0.04832,-0.219845 0.02991,-0.07372 0.07918,-0.147125 0.147798,-0.220224" + inkscape:connector-curvature="0" + id="path3867" /> + <path + d="m 18.630854,41.246205 0.610015,0.126766 -0.06756,0.325086 -0.610014,-0.126766 -0.263863,1.269749 -0.267718,-0.05563 -1.560346,-1.610929 0.07511,-0.36142 1.812833,0.37672 0.07868,-0.37863 0.271543,0.05643 -0.07868,0.37863 m -1.76374,-0.02739 c 0.0058,0.0039 0.01727,0.0129 0.03427,0.02707 0.01573,0.01391 0.03374,0.02962 0.05404,0.04714 0.0203,0.01752 0.0411,0.03581 0.06241,0.05486 0.0203,0.01752 0.03704,0.03297 0.05021,0.04634 l 0.873873,0.901738 c 0.0089,0.0085 0.02027,0.02084 0.0342,0.03703 0.01419,0.01492 0.02888,0.03061 0.04408,0.04706 0.01393,0.01619 0.02785,0.03239 0.04177,0.04858 0.01392,0.01619 0.02455,0.02904 0.03189,0.03854 l 0.197897,-0.952311 -1.424642,-0.296051" + inkscape:connector-curvature="0" + id="path3869" /> + <path + d="m 19.399774,40.683288 -0.238326,-0.06876 c -0.127964,-0.106035 -0.234444,-0.220778 -0.319439,-0.344229 -0.08588,-0.125063 -0.159246,-0.251257 -0.220086,-0.378581 -0.06209,-0.127684 -0.117659,-0.252132 -0.166711,-0.373345 -0.04869,-0.122462 -0.100265,-0.234917 -0.154731,-0.337365 -0.05446,-0.102444 -0.117193,-0.190335 -0.188189,-0.263672 -0.07063,-0.07458 -0.159744,-0.127399 -0.267336,-0.158443 -0.07506,-0.02166 -0.143991,-0.02935 -0.206787,-0.02307 -0.06404,0.0059 -0.121594,0.02455 -0.172651,0.05589 -0.05105,0.03135 -0.09463,0.07434 -0.130719,0.128974 -0.03698,0.05303 -0.06594,0.115819 -0.08687,0.188378 -0.01949,0.06756 -0.02852,0.13407 -0.02708,0.199533 0.0018,0.06421 0.01479,0.124881 0.03897,0.181997 0.02418,0.05712 0.06008,0.108811 0.107717,0.155078 0.04675,0.04466 0.105762,0.08201 0.177045,0.112064 l -0.131524,0.336087 c -0.09183,-0.03869 -0.173699,-0.09077 -0.245611,-0.15624 -0.07191,-0.06547 -0.12867,-0.143506 -0.17029,-0.234115 -0.04287,-0.09097 -0.06782,-0.192355 -0.07487,-0.304159 -0.0067,-0.113052 0.0093,-0.236511 0.04791,-0.370375 0.0379,-0.131359 0.08729,-0.243821 0.148161,-0.337385 0.06088,-0.09356 0.13207,-0.166528 0.213583,-0.218903 0.08188,-0.05362 0.173268,-0.0862 0.27417,-0.09775 0.100906,-0.01154 0.210158,-3.48e-4 0.327755,0.03358 0.08883,0.02563 0.16858,0.06626 0.239262,0.121883 0.07105,0.05438 0.135087,0.118933 0.192126,0.193661 0.0574,0.07348 0.109775,0.154997 0.157118,0.244545 0.04734,0.08955 0.09253,0.181869 0.135571,0.276951 0.04179,0.09472 0.08339,0.190072 0.124816,0.286044 0.04018,0.09561 0.08224,0.187029 0.126188,0.274244 0.04431,0.08597 0.09186,0.165412 0.142647,0.238337 0.04953,0.07256 0.105625,0.134147 0.168272,0.184746 l 0.397946,-1.379288 0.287117,0.08284 -0.505148,1.750851" + inkscape:connector-curvature="0" + id="path3871" /> + <path + d="m 20.097629,38.396989 -0.403551,-0.141786 0.126248,-0.359327 0.403551,0.141787 -0.126248,0.359326" + inkscape:connector-curvature="0" + id="path3873" /> + <path + d="m 20.293152,35.445622 c 0.127403,0.05309 0.235975,0.1209 0.325717,0.203432 0.08974,0.08254 0.157297,0.17769 0.202668,0.285461 0.04417,0.107275 0.06375,0.226165 0.05874,0.356672 -0.0045,0.129308 -0.03757,0.267879 -0.09917,0.415713 -0.05559,0.133413 -0.119797,0.243488 -0.192615,0.330225 -0.07232,0.08554 -0.149793,0.151289 -0.232426,0.19726 -0.08384,0.04547 -0.170925,0.07336 -0.26127,0.08368 -0.08984,0.0091 -0.180338,0.0046 -0.271484,-0.01368 l 0.09886,-0.343898 c 0.05359,0.0068 0.108224,0.0077 0.163913,0.0027 0.05449,-0.0055 0.108273,-0.02118 0.161359,-0.04702 0.05238,-0.02754 0.101914,-0.06685 0.14859,-0.117936 0.04597,-0.05278 0.08699,-0.122443 0.123051,-0.208981 0.03506,-0.08413 0.05424,-0.165713 0.05755,-0.244741 0.0021,-0.07953 -0.01207,-0.153845 -0.04251,-0.222957 -0.02995,-0.07031 -0.07607,-0.133965 -0.138367,-0.190959 -0.0623,-0.05699 -0.140923,-0.10527 -0.235874,-0.144837 -0.07812,-0.03255 -0.154897,-0.04973 -0.230318,-0.05154 -0.07662,-0.0023 -0.148136,0.01022 -0.214544,0.03755 -0.06761,0.02684 -0.128907,0.06901 -0.183897,0.126499 -0.05449,0.05629 -0.09976,0.127704 -0.135822,0.21424 -0.02254,0.05409 -0.03851,0.10597 -0.04793,0.155648 -0.0094,0.04968 -0.01397,0.09786 -0.01367,0.144531 8.02e-4,0.04547 0.0059,0.08919 0.01517,0.13116 0.0086,0.04027 0.01918,0.07923 0.0317,0.116888 l -0.132218,0.317305 -1.331266,-0.654175 0.601743,-1.444098 0.275839,0.11494 -0.47854,1.148427 0.785599,0.384482 c -0.02043,-0.07622 -0.02824,-0.164112 -0.02343,-0.263673 0.0036,-0.100058 0.0302,-0.209583 0.07979,-0.328574 0.05259,-0.126199 0.119146,-0.231766 0.199676,-0.316702 0.08053,-0.08493 0.171027,-0.148081 0.271488,-0.189447 0.09926,-0.04186 0.205581,-0.06174 0.318962,-0.05964 0.113381,0.0021 0.228365,0.02745 0.34495,0.07603" + inkscape:connector-curvature="0" + id="path3875" /> + <path + d="M 21.868617,34.296638 20.68612,33.666653 c -0.09078,-0.04836 -0.169691,-0.08303 -0.23672,-0.103985 -0.06703,-0.02095 -0.126275,-0.02744 -0.177743,-0.01945 -0.052,0.0062 -0.09711,0.0272 -0.135312,0.06291 -0.03935,0.0351 -0.07587,0.08425 -0.109539,0.147452 -0.0349,0.06551 -0.05321,0.131728 -0.05494,0.198669 -0.0029,0.06633 0.01028,0.131622 0.0395,0.19587 0.02867,0.06249 0.0737,0.123359 0.135077,0.182614 0.06084,0.05749 0.137803,0.111038 0.230885,0.160627 l 1.080796,0.575804 -0.164385,0.308552 -1.466916,-0.781513 c -0.03907,-0.02081 -0.08017,-0.04197 -0.123305,-0.06348 -0.04367,-0.02326 -0.08477,-0.04442 -0.123305,-0.06348 -0.03968,-0.01966 -0.07362,-0.03627 -0.101815,-0.04982 -0.02819,-0.01354 -0.04662,-0.02188 -0.05527,-0.02502 l 0.156119,-0.293038 c 0.0064,0.0019 0.02248,0.009 0.04838,0.02135 0.02589,0.01232 0.05581,0.02678 0.08975,0.04339 0.0334,0.01485 0.06765,0.03088 0.102733,0.04809 0.03394,0.01661 0.0624,0.03103 0.08538,0.04328 l 0.0028,-0.0052 c -0.03932,-0.05635 -0.07224,-0.112252 -0.09877,-0.167695 -0.02652,-0.05544 -0.0434,-0.11238 -0.05063,-0.170819 -0.0078,-0.0602 -0.005,-0.122162 0.0083,-0.185895 0.01276,-0.06549 0.03874,-0.135011 0.07792,-0.20856 0.07531,-0.141345 0.162847,-0.237815 0.262623,-0.289409 0.100391,-0.05274 0.220638,-0.06244 0.360741,-0.02911 l 0.0028,-0.0052 c -0.03932,-0.05635 -0.07163,-0.1134 -0.09693,-0.171142 -0.0253,-0.05774 -0.04065,-0.11755 -0.04604,-0.179438 -0.0065,-0.06249 -0.0025,-0.126757 0.01198,-0.19279 0.01337,-0.06664 0.03965,-0.136733 0.07884,-0.210283 0.0502,-0.09423 0.106006,-0.168511 0.167409,-0.222846 0.06202,-0.05548 0.131087,-0.09097 0.207214,-0.106481 0.07613,-0.0155 0.161645,-0.01125 0.256554,0.01275 0.09376,0.0234 0.198099,0.06571 0.313016,0.126928 l 1.242829,0.662128 -0.163466,0.306829 -1.182497,-0.629986 c -0.09078,-0.04836 -0.169691,-0.08303 -0.236719,-0.103984 -0.06703,-0.02095 -0.126276,-0.02744 -0.177743,-0.01945 -0.052,0.0062 -0.09711,0.0272 -0.135312,0.06291 -0.03935,0.0351 -0.07587,0.08425 -0.109539,0.147452 -0.0349,0.06551 -0.05379,0.131423 -0.05667,0.197751 -0.004,0.06572 0.008,0.130399 0.03605,0.194033 0.02867,0.06249 0.0737,0.123361 0.135077,0.182614 0.06199,0.05811 0.140676,0.112569 0.236057,0.163382 l 1.080795,0.575804 -0.163465,0.306828" + inkscape:connector-curvature="0" + id="path3877" /> + <path + d="M 23.584114,31.437572 22.48027,30.678158 c -0.08475,-0.0583 -0.159236,-0.101646 -0.223471,-0.130035 -0.06424,-0.02839 -0.122372,-0.04151 -0.174413,-0.03939 -0.05237,3.21e-4 -0.09956,0.01607 -0.141546,0.04723 -0.04306,0.03043 -0.08489,0.07515 -0.12548,0.134149 -0.04207,0.06115 -0.06774,0.12488 -0.07701,0.191199 -0.01035,0.06558 -0.0046,0.131942 0.01714,0.199075 0.02144,0.06533 0.05931,0.130889 0.113605,0.196692 0.05396,0.06399 0.124392,0.12588 0.211282,0.185658 l 1.008907,0.6941 -0.198156,0.288029 -1.369346,-0.942072 c -0.03647,-0.02509 -0.07492,-0.05075 -0.115353,-0.07699 -0.04076,-0.02804 -0.07921,-0.05371 -0.115353,-0.07699 -0.03721,-0.02402 -0.06906,-0.04435 -0.09554,-0.06099 -0.02648,-0.01664 -0.04385,-0.027 -0.0521,-0.0311 l 0.188193,-0.273547 c 0.0061,0.0026 0.02132,0.01151 0.04566,0.02667 0.02434,0.01516 0.05243,0.03291 0.08428,0.05324 0.03151,0.01852 0.06373,0.03831 0.09665,0.05938 0.03185,0.02033 0.0585,0.03788 0.07995,0.05263 l 0.0033,-0.0048 c -0.0327,-0.06043 -0.05911,-0.119687 -0.07921,-0.17777 -0.0201,-0.05808 -0.03044,-0.11656 -0.03103,-0.175441 -9.19e-4,-0.06069 0.0088,-0.121945 0.02923,-0.18377 0.02007,-0.06363 0.05373,-0.129777 0.100956,-0.198434 0.09078,-0.131944 0.188646,-0.217918 0.293608,-0.257922 0.105701,-0.04107 0.226275,-0.03714 0.361722,0.01178 l 0.0033,-0.0048 c -0.03271,-0.06043 -0.05837,-0.120759 -0.077,-0.180988 -0.01862,-0.06022 -0.02712,-0.121386 -0.02549,-0.183486 5.57e-4,-0.06283 0.01178,-0.126235 0.03366,-0.190207 0.02081,-0.0647 0.05483,-0.131385 0.102063,-0.200043 0.06052,-0.08796 0.124348,-0.15547 0.19149,-0.202529 0.06788,-0.04812 0.140517,-0.0756 0.217907,-0.08242 0.07739,-0.0068 0.161882,0.0071 0.253476,0.04163 0.09052,0.03383 0.189418,0.08765 0.296692,0.161443 L 24.473049,30.145463 24.276,30.431884 23.172156,29.67247 c -0.08475,-0.0583 -0.159237,-0.101645 -0.223471,-0.130036 -0.06424,-0.02838 -0.122373,-0.04151 -0.174413,-0.03939 -0.05237,3.22e-4 -0.09956,0.01607 -0.141546,0.04723 -0.04306,0.03043 -0.08489,0.07515 -0.125481,0.134148 -0.04207,0.06115 -0.06827,0.124513 -0.07862,0.190092 -0.01142,0.06485 -0.0068,0.130467 0.01392,0.196861 0.02144,0.06533 0.05931,0.13089 0.113605,0.196692 0.05504,0.06473 0.127072,0.127726 0.216109,0.188979 l 1.008907,0.6941 -0.197049,0.28642" + inkscape:connector-curvature="0" + id="path3879" /> + <path + d="m 24.787912,28.352718 -0.23516,-0.205805 0.643142,-0.734876 0.235161,0.205805 -0.643143,0.734876" + inkscape:connector-curvature="0" + id="path3881" /> + <path + d="m 27.872659,25.20214 c 0.09453,0.100568 0.165856,0.206864 0.213976,0.318889 0.04812,0.112029 0.07083,0.226493 0.06814,0.343395 -0.0036,0.115955 -0.03437,0.23245 -0.09233,0.349485 -0.05702,0.116144 -0.143878,0.229062 -0.260572,0.338753 -0.105311,0.09899 -0.208932,0.173163 -0.310863,0.222515 -0.100984,0.04846 -0.19858,0.07676 -0.292789,0.0849 -0.0951,0.0072 -0.185981,-0.003 -0.272638,-0.03054 -0.08571,-0.02844 -0.166417,-0.06963 -0.242126,-0.123555 l 0.230914,-0.273348 c 0.04611,0.02814 0.09559,0.05132 0.148458,0.06953 0.05197,0.01727 0.107462,0.02497 0.166474,0.02311 0.05907,-0.0037 0.120346,-0.01931 0.183836,-0.04682 0.06355,-0.02935 0.129474,-0.07613 0.197784,-0.140346 0.06641,-0.06243 0.117291,-0.129016 0.152642,-0.199774 0.03446,-0.0717 0.05193,-0.145316 0.05243,-0.220836 0.0014,-0.07641 -0.0146,-0.153362 -0.04813,-0.230856 -0.03353,-0.07749 -0.08552,-0.153712 -0.15597,-0.228665 -0.05797,-0.06167 -0.120992,-0.108752 -0.189073,-0.141257 -0.06897,-0.03345 -0.13935,-0.05129 -0.211131,-0.05351 -0.07267,-0.0032 -0.145858,0.01023 -0.219556,0.04019 -0.07275,0.02907 -0.143278,0.07571 -0.211587,0.139918 -0.04269,0.04013 -0.0785,0.08094 -0.107417,0.122415 -0.02892,0.04148 -0.05279,0.08357 -0.07161,0.126285 -0.01787,0.04182 -0.03115,0.08378 -0.03982,0.125888 -0.0086,0.04027 -0.01491,0.08014 -0.0189,0.119626 l -0.250467,0.235436 -0.947096,-1.141588 1.139909,-1.071504 0.204669,0.217736 -0.906519,0.85212 0.559531,0.672247 c 0.01254,-0.07791 0.04138,-0.161302 0.0865,-0.250181 0.04423,-0.08982 0.113309,-0.178881 0.207234,-0.267172 0.09962,-0.09364 0.203542,-0.162733 0.311774,-0.207287 0.108231,-0.04455 0.216643,-0.06515 0.325236,-0.06179 0.107699,0.0024 0.212847,0.02777 0.315444,0.07608 0.102595,0.04831 0.197145,0.118481 0.283651,0.210507" + inkscape:connector-curvature="0" + id="path3883" /> + <path + d="m 29.355132,23.367427 c 0.166083,0.20563 0.286234,0.394797 0.360453,0.567502 0.07441,0.170877 0.112865,0.327279 0.115359,0.469207 0.0027,0.140099 -0.02642,0.265704 -0.08731,0.376815 -0.06089,0.111113 -0.143002,0.208395 -0.246321,0.291845 -0.104334,0.08427 -0.216712,0.144073 -0.337135,0.179409 -0.120424,0.03534 -0.248834,0.03695 -0.38523,0.0049 -0.135384,-0.03292 -0.278774,-0.103728 -0.430171,-0.212425 -0.151201,-0.110527 -0.310252,-0.269111 -0.477155,-0.475752 -0.174265,-0.215756 -0.299519,-0.40917 -0.375764,-0.580242 -0.07605,-0.1729 -0.114598,-0.328386 -0.115652,-0.466461 -0.001,-0.138069 0.03051,-0.260635 0.09467,-0.367698 0.06335,-0.108071 0.148709,-0.20547 0.25608,-0.292196 0.102308,-0.08263 0.21194,-0.142725 0.328895,-0.180285 0.117152,-0.03939 0.243107,-0.04404 0.377867,-0.01397 0.134761,0.03008 0.278657,0.100479 0.43169,0.211198 0.152214,0.109712 0.315454,0.272446 0.48972,0.4882 m -0.278053,0.224582 c -0.137449,-0.170173 -0.26171,-0.303297 -0.372783,-0.399373 -0.111892,-0.09708 -0.214588,-0.1631 -0.308091,-0.19805 -0.09432,-0.03596 -0.181395,-0.04429 -0.261223,-0.02501 -0.07963,0.01746 -0.155915,0.05564 -0.228847,0.114541 -0.07698,0.06218 -0.133396,0.131178 -0.16924,0.206991 -0.03584,0.07582 -0.04661,0.164021 -0.03232,0.264612 0.01449,0.09876 0.05743,0.213052 0.1288,0.342862 0.07056,0.128802 0.174149,0.277782 0.310779,0.446942 0.132541,0.164098 0.254347,0.294183 0.36542,0.390256 0.112087,0.09526 0.215699,0.16137 0.310838,0.198342 0.09533,0.03514 0.184141,0.04459 0.266424,0.02834 0.08146,-0.01726 0.159168,-0.05575 0.233113,-0.115476 0.07192,-0.05809 0.124884,-0.125137 0.158896,-0.201148 0.03319,-0.07702 0.04213,-0.16542 0.02682,-0.265196 -0.01512,-0.101605 -0.05745,-0.217217 -0.126988,-0.346836 -0.06853,-0.130434 -0.169065,-0.277701 -0.301605,-0.441799" + inkscape:connector-curvature="0" + id="path3885" /> + <path + d="M 31.579813,23.488032 30.839466,22.37131 c -0.05684,-0.08573 -0.109752,-0.153761 -0.158736,-0.204087 -0.04899,-0.05032 -0.09801,-0.08421 -0.147082,-0.101676 -0.0487,-0.01926 -0.09835,-0.02228 -0.148945,-0.009 -0.05131,0.01215 -0.106812,0.03801 -0.166501,0.07758 -0.06186,0.04101 -0.109475,0.09055 -0.142849,0.148601 -0.03409,0.05697 -0.05358,0.120664 -0.05845,0.191071 -0.0045,0.06861 0.0061,0.143568 0.03193,0.224888 0.02616,0.07952 0.06838,0.163229 0.126655,0.251133 l 0.676673,1.020677 -0.29139,0.193181 -0.918418,-1.385321 c -0.02446,-0.0369 -0.05055,-0.07506 -0.07825,-0.1145 -0.02734,-0.04124 -0.05342,-0.07941 -0.07825,-0.1145 -0.02555,-0.03618 -0.0475,-0.06693 -0.06585,-0.09226 -0.01835,-0.02532 -0.03059,-0.04143 -0.03671,-0.04831 l 0.276739,-0.183468 c 0.0047,0.0047 0.01548,0.01864 0.03239,0.04179 0.01692,0.02316 0.03635,0.05011 0.0583,0.08086 0.02232,0.02895 0.04481,0.05934 0.06748,0.09118 0.02195,0.03076 0.04012,0.05698 0.05451,0.07869 l 0.0049,-0.0032 c -0.0078,-0.06827 -0.01013,-0.133102 -0.0071,-0.194489 0.003,-0.06138 0.01529,-0.119494 0.03674,-0.174333 0.02181,-0.05664 0.05373,-0.109825 0.09575,-0.159556 0.04238,-0.05153 0.0983,-0.100321 0.167761,-0.14637 0.133486,-0.08849 0.256382,-0.131695 0.36869,-0.129604 0.113392,0.0014 0.223774,0.05005 0.331146,0.146026 l 0.0049,-0.0032 c -0.0078,-0.06827 -0.009,-0.133821 -0.0038,-0.196648 0.0052,-0.06282 0.02018,-0.122731 0.04488,-0.179729 0.02398,-0.05808 0.05807,-0.112702 0.10226,-0.163873 0.04347,-0.05225 0.09993,-0.1014 0.16939,-0.14745 0.08899,-0.05899 0.173414,-0.09778 0.253273,-0.116357 0.08094,-0.01929 0.158582,-0.01765 0.232919,0.0049 0.07433,0.02258 0.14753,0.06701 0.219588,0.133281 0.07134,0.06519 0.142978,0.152046 0.214928,0.260568 l 0.77812,1.173697 -0.289762,0.192102 -0.740347,-1.116722 c -0.05684,-0.08573 -0.109752,-0.153761 -0.158736,-0.204087 -0.04899,-0.05032 -0.09801,-0.08421 -0.147081,-0.101676 -0.0487,-0.01926 -0.09835,-0.02228 -0.148945,-0.009 -0.05131,0.01215 -0.106814,0.03801 -0.166501,0.07758 -0.06186,0.04101 -0.109836,0.09 -0.143929,0.146973 -0.03481,0.05589 -0.05502,0.118494 -0.06061,0.187815 -0.0045,0.06861 0.0061,0.143569 0.03193,0.224888 0.02688,0.0806 0.07017,0.165943 0.129893,0.256016 l 0.676672,1.020678 -0.289761,0.192101" + inkscape:connector-curvature="0" + id="path3887" /> + <path + d="m 34.448904,21.789158 -0.609488,-1.193191 c -0.04679,-0.0916 -0.09168,-0.165173 -0.134671,-0.220709 -0.04299,-0.05553 -0.08787,-0.09474 -0.134657,-0.117637 -0.04622,-0.02464 -0.09521,-0.03325 -0.14697,-0.02581 -0.05236,0.0063 -0.110422,0.0257 -0.174197,0.05828 -0.0661,0.03376 -0.119002,0.0776 -0.158718,0.131517 -0.04031,0.05276 -0.06686,0.113841 -0.07966,0.183247 -0.01223,0.06766 -0.01012,0.143342 0.0063,0.227054 0.01701,0.08196 0.0495,0.169907 0.09748,0.263831 l 0.557069,1.09057 -0.311343,0.159035 -0.756085,-1.480183 c -0.02014,-0.03942 -0.04174,-0.08029 -0.06482,-0.122605 -0.02251,-0.04406 -0.04411,-0.08493 -0.06482,-0.122605 -0.0213,-0.03883 -0.03963,-0.07187 -0.05501,-0.09911 -0.01537,-0.02723 -0.02572,-0.04462 -0.03102,-0.05214 l 0.295689,-0.15104 c 0.0041,0.0052 0.01328,0.02027 0.02747,0.04519 0.01419,0.02492 0.03045,0.0539 0.04879,0.08693 0.0189,0.03129 0.03782,0.06402 0.05675,0.09822 0.01834,0.03304 0.03343,0.06115 0.04527,0.08434 l 0.0052,-0.0027 c -9e-6,-0.06871 0.005,-0.133394 0.01493,-0.194045 0.01,-0.06065 0.02869,-0.117002 0.0562,-0.169068 0.02807,-0.05381 0.06579,-0.103054 0.113156,-0.147721 0.04793,-0.04642 0.109007,-0.08858 0.183219,-0.126487 0.142627,-0.07285 0.269616,-0.101897 0.380968,-0.08713 0.112512,0.01417 0.21669,0.07501 0.312536,0.182492 l 0.0052,-0.0027 c -1e-5,-0.06871 0.0061,-0.133986 0.01841,-0.195821 0.01228,-0.06183 0.03391,-0.119667 0.06489,-0.173511 0.03039,-0.055 0.07043,-0.105423 0.120114,-0.151275 0.04909,-0.04701 0.110745,-0.08947 0.184959,-0.127376 0.09508,-0.04857 0.183347,-0.07757 0.264794,-0.08701 0.0826,-0.01002 0.15956,3.77e-4 0.230871,0.03121 0.07131,0.03083 0.139019,0.08324 0.203131,0.157228 0.06352,0.07283 0.124892,0.167221 0.184125,0.283175 l 0.640584,1.254068 -0.309603,0.158147 -0.609489,-1.193191 c -0.04679,-0.0916 -0.09168,-0.165173 -0.134671,-0.220709 -0.04299,-0.05553 -0.08788,-0.09474 -0.134657,-0.117636 -0.04622,-0.02464 -0.09521,-0.03325 -0.14697,-0.02581 -0.05236,0.0063 -0.110423,0.0257 -0.174197,0.05828 -0.0661,0.03376 -0.119299,0.07702 -0.159607,0.129777 -0.0409,0.0516 -0.06805,0.111522 -0.08143,0.179768 -0.01223,0.06766 -0.01012,0.143343 0.0063,0.227055 0.0176,0.08312 0.05098,0.172806 0.100147,0.269048 l 0.557069,1.09057 -0.309604,0.158147" + inkscape:connector-curvature="0" + id="path3889" /> + <path + d="m 42.744275,18.955546 -0.04478,-0.295454 0.693255,-0.105066 -0.317246,-2.093284 -0.547647,0.531421 -0.04975,-0.328283 0.576028,-0.539672 0.320559,-0.04858 0.367584,2.425428 0.662358,-0.100383 0.04478,0.295454 -1.705138,0.258421" + inkscape:connector-curvature="0" + id="path3891" /> + <path + d="m 44.849923,16.947576 -0.03792,-0.402515 0.379181,-0.03572 0.03792,0.402515 -0.379181,0.03572 m 0.16027,1.701453 -0.03791,-0.402515 0.379181,-0.03572 0.03791,0.402515 -0.379181,0.03572" + inkscape:connector-curvature="0" + id="path3893" /> + <path + d="m 46.054835,18.552163 -0.01133,-0.298614 0.700668,-0.02658 -0.08025,-2.115666 -0.603843,0.466582 -0.01259,-0.331793 0.632971,-0.471596 0.323985,-0.01229 0.09298,2.451363 0.66944,-0.02539 0.01133,0.298613 -1.72337,0.06537" + inkscape:connector-curvature="0" + id="path3895" /> + <path + d="m 48.342118,18.501344 0.0076,-0.427668 0.3808,0.0067 -0.0076,0.427668 -0.380799,-0.0067" + inkscape:connector-curvature="0" + id="path3897" /> + <path + d="m 50.84888,18.003867 -0.04578,0.621362 -0.331133,-0.0244 0.04578,-0.621362 -1.293369,-0.09529 0.02009,-0.272698 1.392697,-1.757888 0.368143,0.02712 -0.13605,1.846558 0.385673,0.02841 -0.02038,0.276594 -0.385673,-0.02841 M 50.64504,16.251727 c -0.0031,0.0063 -0.01053,0.01881 -0.02235,0.03752 -0.01173,0.01742 -0.02495,0.03733 -0.03965,0.05975 -0.01471,0.02242 -0.03011,0.04544 -0.04621,0.06906 -0.01471,0.02242 -0.02783,0.04104 -0.03937,0.05585 l -0.779521,0.984446 c -0.0073,0.0099 -0.018,0.02283 -0.03223,0.03875 -0.01293,0.01602 -0.02656,0.03264 -0.04088,0.04987 -0.01423,0.01592 -0.02846,0.03185 -0.04269,0.04777 -0.01423,0.01593 -0.02557,0.02815 -0.03404,0.03666 l 0.970027,0.07147 0.106917,-1.451144" + inkscape:connector-curvature="0" + id="path3899" /> + <path + d="m 77.021288,37.280268 c -0.21155,0.08812 -0.411725,0.134119 -0.600525,0.138007 -0.187603,0.0034 -0.359123,-0.02744 -0.514564,-0.09245 -0.154241,-0.06552 -0.291149,-0.162243 -0.410726,-0.290158 -0.117876,-0.127218 -0.213112,-0.277969 -0.285709,-0.452254 l -0.395782,-0.950163 2.540378,-1.058172 0.34997,0.840182 c 0.08161,0.195922 0.132067,0.386482 0.151381,0.571681 0.02101,0.185899 0.0052,0.359625 -0.04738,0.521179 -0.0514,0.161051 -0.141462,0.307175 -0.270179,0.438372 -0.128222,0.132397 -0.30051,0.243656 -0.516863,0.333779 m -0.144194,-0.346169 c 0.171881,-0.0716 0.308258,-0.15732 0.409132,-0.257168 0.102072,-0.100351 0.173648,-0.211271 0.21473,-0.332759 0.04107,-0.121491 0.05386,-0.251648 0.03835,-0.390471 -0.01431,-0.139325 -0.05226,-0.282909 -0.113836,-0.430751 l -0.203524,-0.488604 -1.98867,0.828363 0.235817,0.566131 c 0.05557,0.133418 0.128528,0.247609 0.218863,0.342571 0.09083,0.09616 0.196195,0.167939 0.316083,0.215329 0.119885,0.04739 0.253296,0.06798 0.400234,0.06179 0.146934,-0.0062 0.30454,-0.04434 0.472818,-0.114432" + inkscape:connector-curvature="0" + id="path3901" /> + <path + d="m 76.885764,38.221869 c -0.105493,0.03348 -0.199569,0.07495 -0.28223,0.124408 -0.08103,0.05031 -0.146718,0.108039 -0.197074,0.1732 -0.04872,0.06601 -0.07985,0.140094 -0.09339,0.222259 -0.0123,0.08177 -0.0027,0.172297 0.02882,0.271585 0.04608,0.145204 0.112078,0.251989 0.197982,0.320352 0.0863,0.0696 0.179046,0.105738 0.278252,0.108406 l 0.0096,0.320723 c -0.06255,-0.0034 -0.128468,-0.01524 -0.197767,-0.03559 -0.06767,-0.01951 -0.134502,-0.05362 -0.20051,-0.102342 -0.06477,-0.04912 -0.127209,-0.116729 -0.187324,-0.202837 -0.05848,-0.08526 -0.108991,-0.194913 -0.15153,-0.328948 -0.09453,-0.297859 -0.07788,-0.553139 0.04997,-0.76584 0.128238,-0.211461 0.367348,-0.37273 0.717332,-0.483807 0.188643,-0.05987 0.355605,-0.0869 0.500887,-0.0811 0.146521,0.0054 0.273735,0.03607 0.381645,0.09198 0.107906,0.05591 0.197186,0.132768 0.267842,0.23056 0.07189,0.0974 0.127534,0.208151 0.166925,0.332259 0.05357,0.168785 0.07097,0.318313 0.05221,0.448583 -0.01837,0.131509 -0.06513,0.246755 -0.140265,0.345739 -0.07351,0.09983 -0.170886,0.184695 -0.292138,0.2546 -0.120861,0.07114 -0.256997,0.130742 -0.408406,0.178798 l -0.04468,0.01418 -0.456124,-1.437167 m 0.603131,1.009371 c 0.206314,-0.08597 0.343694,-0.188998 0.41214,-0.309078 0.06968,-0.120476 0.07794,-0.264486 0.02477,-0.43203 -0.01773,-0.05585 -0.04574,-0.111846 -0.08405,-0.167991 -0.03668,-0.0553 -0.08625,-0.101724 -0.148708,-0.139275 -0.06247,-0.03755 -0.139122,-0.06172 -0.229972,-0.0725 -0.08961,-0.01118 -0.196018,5.4e-5 -0.319218,0.03369 l 0.345047,1.087183" + inkscape:connector-curvature="0" + id="path3903" /> + <path + d="m 77.456336,41.797791 c -0.09624,0.02305 -0.186892,0.02469 -0.271967,0.0049 -0.08351,-0.01882 -0.159712,-0.05747 -0.228616,-0.115944 -0.06764,-0.05878 -0.127824,-0.136745 -0.180556,-0.233902 -0.05116,-0.0962 -0.09267,-0.210774 -0.124523,-0.343729 -0.02852,-0.119029 -0.0448,-0.228935 -0.04887,-0.32972 -0.005,-0.09922 0.0041,-0.189766 0.02731,-0.27165 0.02323,-0.08188 0.06185,-0.155405 0.115865,-0.220563 0.05558,-0.0642 0.128763,-0.119217 0.219538,-0.165065 l 0.131231,0.287896 c -0.103187,0.05551 -0.169818,0.135077 -0.199892,0.238685 -0.02881,0.103304 -0.0238,0.235996 0.01503,0.398077 0.0176,0.07344 0.03874,0.13934 0.06343,0.197694 0.02499,0.05962 0.05483,0.108706 0.08951,0.147262 0.03594,0.03825 0.07706,0.06455 0.12334,0.0789 0.04785,0.01531 0.102169,0.01569 0.16295,0.0011 0.06205,-0.01487 0.109207,-0.04156 0.141485,-0.08009 0.03354,-0.03883 0.05739,-0.08739 0.07155,-0.145677 0.01415,-0.05829 0.02178,-0.127061 0.02287,-0.206319 0.0027,-0.0783 0.0054,-0.164646 0.0082,-0.259047 0.0018,-0.08746 0.0063,-0.174901 0.01348,-0.262311 0.0072,-0.08741 0.0244,-0.169196 0.05168,-0.245355 0.02885,-0.0752 0.07071,-0.14079 0.125578,-0.196781 0.05487,-0.05599 0.131057,-0.09567 0.22856,-0.119025 0.187403,-0.0449 0.345783,-0.01255 0.475139,0.09705 0.130921,0.110561 0.227022,0.293733 0.288302,0.549516 0.0543,0.226659 0.05749,0.416022 0.0096,0.568091 -0.04762,0.153333 -0.155187,0.268811 -0.3227,0.346434 l -0.111703,-0.298599 c 0.05045,-0.02414 0.08976,-0.05565 0.11794,-0.09453 0.02944,-0.03919 0.04976,-0.08289 0.06098,-0.131095 0.01248,-0.04851 0.01663,-0.101057 0.01245,-0.157628 -0.0026,-0.05561 -0.0109,-0.112539 -0.02485,-0.170786 -0.03701,-0.154483 -0.08774,-0.262834 -0.152183,-0.325052 -0.06445,-0.06222 -0.144155,-0.08195 -0.239122,-0.0592 -0.05572,0.01335 -0.09875,0.03771 -0.129099,0.0731 -0.02878,0.03635 -0.05007,0.08162 -0.06387,0.135805 -0.01223,0.05515 -0.01965,0.119185 -0.02226,0.192113 -0.0013,0.07262 -0.0023,0.152516 -0.0028,0.239677 -8.86e-4,0.05779 -0.0027,0.117141 -0.0055,0.178066 -0.0015,0.06062 -0.0073,0.120253 -0.01739,0.178897 -0.0085,0.0596 -0.02231,0.116474 -0.04147,0.170607 -0.0176,0.05509 -0.04304,0.105374 -0.07633,0.150841 -0.03329,0.04546 -0.07537,0.085 -0.12623,0.11861 -0.05056,0.03487 -0.11256,0.06111 -0.186001,0.0787" + inkscape:connector-curvature="0" + id="path3905" /> + <path + d="m 79.476583,41.866986 0.330152,-0.06208 0.06496,0.345508 -0.330152,0.06208 -0.06496,-0.345509 m -2.518371,0.473514 2.076888,-0.390504 0.06496,0.345508 -2.076888,0.390504 -0.06496,-0.345508" + inkscape:connector-curvature="0" + id="path3907" /> + <path + d="m 76.409909,44.121315 c -0.01605,-0.120027 -0.01802,-0.228141 -0.0059,-0.324341 0.0121,-0.0962 0.03698,-0.18032 0.07464,-0.252352 0.03637,-0.07186 0.08342,-0.132668 0.141132,-0.182422 0.05772,-0.04976 0.124086,-0.08884 0.199106,-0.117265 l 0.09718,0.343668 c -0.09369,0.03617 -0.161082,0.09707 -0.20218,0.182702 -0.04221,0.08709 -0.05469,0.195167 -0.03744,0.324228 0.01053,0.07872 0.03107,0.148887 0.06164,0.210484 0.03057,0.0616 0.07339,0.1117 0.128476,0.150315 0.05379,0.03878 0.121045,0.06526 0.20176,0.07943 0.08071,0.01417 0.176567,0.01383 0.287559,-10e-4 l 0.336846,-0.04504 -5.18e-4,-0.0039 c -0.05637,-0.01874 -0.111659,-0.04419 -0.165878,-0.07635 -0.05276,-0.03104 -0.101558,-0.07181 -0.146406,-0.122301 -0.04467,-0.0492 -0.08346,-0.108386 -0.116353,-0.177552 -0.0316,-0.06934 -0.05362,-0.150473 -0.06604,-0.243395 -0.01777,-0.132932 -0.01111,-0.250084 0.02001,-0.351454 0.03257,-0.100254 0.08933,-0.186663 0.170272,-0.259228 0.08111,-0.07127 0.185592,-0.129908 0.313437,-0.175902 0.129307,-0.04488 0.281077,-0.07896 0.455308,-0.102258 0.167777,-0.02243 0.320589,-0.02907 0.458436,-0.01991 0.138017,0.01045 0.257629,0.04043 0.358837,0.08996 0.102667,0.05064 0.185166,0.122372 0.247498,0.215191 0.06379,0.09394 0.105265,0.212533 0.124421,0.35579 0.01984,0.148418 0.0028,0.281405 -0.05109,0.398962 -0.05245,0.118673 -0.137292,0.216063 -0.254541,0.29217 l 5.18e-4,0.0039 c 0.03226,-0.0043 0.06849,-0.0085 0.108669,-0.01256 0.04035,-0.0028 0.07804,-0.0058 0.113059,-0.0092 0.03648,-0.0023 0.0678,-0.0038 0.09396,-0.0047 0.02616,-8.71e-4 0.04134,-2.75e-4 0.04556,0.0018 l 0.04426,0.331039 c -0.01179,2.6e-4 -0.03197,0.0016 -0.06053,0.0042 -0.02728,0.0023 -0.06036,0.0054 -0.09925,0.0093 -0.03889,0.0039 -0.0823,0.0084 -0.130223,0.01347 -0.04646,0.0062 -0.09486,0.01268 -0.145192,0.01941 l -1.600987,0.214061 c -0.292966,0.03917 -0.522676,-0.0037 -0.689131,-0.128556 -0.167573,-0.123414 -0.271204,-0.333538 -0.310893,-0.630374 m 1.940999,0.280395 c 0.145836,-0.0195 0.268222,-0.05229 0.367157,-0.09835 0.100395,-0.04495 0.180053,-0.09764 0.238973,-0.158065 0.05892,-0.06042 0.09938,-0.126264 0.121379,-0.197515 0.02217,-0.06996 0.0286,-0.13979 0.01928,-0.209482 -0.01191,-0.08905 -0.03766,-0.163771 -0.07726,-0.224159 -0.03943,-0.0591 -0.09555,-0.105456 -0.168353,-0.139072 -0.07134,-0.0325 -0.160665,-0.05208 -0.267963,-0.05876 -0.105837,-0.0056 -0.231029,0.0013 -0.375575,0.02066 -0.151,0.02019 -0.27683,0.04687 -0.377489,0.08003 -0.0992,0.03428 -0.177653,0.0763 -0.23537,0.126055 -0.05772,0.04975 -0.0959,0.108062 -0.114547,0.174926 -0.01865,0.06686 -0.0221,0.144174 -0.01037,0.231936 0.0093,0.06969 0.03322,0.135463 0.0717,0.197316 0.03866,0.06314 0.09379,0.116855 0.165392,0.161143 0.0716,0.04428 0.160542,0.07574 0.266814,0.09438 0.106271,0.01863 0.23168,0.01828 0.376228,-0.001" + inkscape:connector-curvature="0" + id="path3909" /> + <path + d="m 77.478883,46.76703 1.337606,-0.07741 c 0.102691,-0.0059 0.188034,-0.01871 0.256028,-0.03829 0.06806,-0.01829 0.12192,-0.04553 0.161563,-0.08174 0.04094,-0.03628 0.06824,-0.08286 0.08191,-0.139731 0.01504,-0.05565 0.02019,-0.124422 0.01545,-0.206315 -0.0048,-0.0832 -0.02413,-0.157725 -0.05794,-0.223589 -0.03244,-0.06464 -0.07799,-0.119392 -0.136671,-0.164253 -0.05731,-0.04364 -0.127658,-0.07609 -0.211055,-0.09734 -0.0821,-0.02134 -0.175796,-0.02895 -0.281087,-0.02286 l -1.222564,0.07075 -0.02031,-0.350976 1.659333,-0.09603 c 0.0442,-0.0026 0.0903,-0.0059 0.138327,-0.01 0.0494,-0.0029 0.0955,-0.0062 0.138327,-0.01 0.04412,-0.0039 0.08174,-0.0073 0.112867,-0.01044 0.03112,-0.0031 0.05119,-0.0056 0.06022,-0.0074 l 0.01918,0.331477 c -0.0064,0.0017 -0.0239,0.004 -0.05242,0.0069 -0.02852,0.003 -0.0616,0.0062 -0.09922,0.0097 -0.03625,0.0047 -0.07383,0.0088 -0.112753,0.01239 -0.03762,0.0035 -0.06943,0.006 -0.09543,0.0075 l 3.39e-4,0.0058 c 0.06305,0.03026 0.12044,0.06411 0.17217,0.101551 0.05173,0.03744 0.09603,0.08183 0.132916,0.133168 0.03818,0.05126 0.06836,0.110818 0.09055,0.178661 0.02348,0.06777 0.03786,0.147145 0.04313,0.23814 0.0068,0.116991 -0.0017,0.218561 -0.02541,0.304711 -0.02371,0.08615 -0.06388,0.158251 -0.120517,0.216309 -0.05664,0.05806 -0.131688,0.102178 -0.22515,0.13237 -0.09209,0.03141 -0.20313,0.05088 -0.333119,0.05841 l -1.405851,0.08136 -0.02043,-0.352926" + inkscape:connector-curvature="0" + id="path3911" /> + <path + d="m 78.487682,47.938431 c -0.110662,-0.0018 -0.213045,0.0076 -0.307147,0.02813 -0.09282,0.02191 -0.17347,0.05574 -0.241943,0.101487 -0.06719,0.04707 -0.12028,0.107402 -0.159261,0.180988 -0.03768,0.07361 -0.05738,0.162485 -0.0591,0.266639 -0.0025,0.152321 0.02607,0.274555 0.08575,0.3667 0.05966,0.09345 0.136094,0.157216 0.229294,0.191313 l -0.09298,0.3071 c -0.05822,-0.0231 -0.116941,-0.05533 -0.176161,-0.09667 -0.05794,-0.04003 -0.110448,-0.09364 -0.157522,-0.160827 -0.04577,-0.06717 -0.08345,-0.15114 -0.113043,-0.251901 -0.02831,-0.09944 -0.0413,-0.219463 -0.03898,-0.360068 0.0052,-0.312458 0.102183,-0.549169 0.291065,-0.710134 0.18886,-0.159663 0.466859,-0.236462 0.833997,-0.230398 0.197888,0.0033 0.364774,0.03077 0.500659,0.0825 0.137183,0.05175 0.248028,0.1213 0.332537,0.208645 0.0845,0.08734 0.144689,0.188613 0.180554,0.303805 0.03716,0.115212 0.05467,0.237914 0.05252,0.368105 -0.0029,0.177058 -0.03401,0.324351 -0.09325,0.44188 -0.05926,0.118827 -0.140261,0.213205 -0.242991,0.283135 -0.101452,0.07125 -0.220775,0.120717 -0.357968,0.148405 -0.137218,0.02898 -0.285242,0.04217 -0.444073,0.03955 l -0.04687,-7.74e-4 0.0249,-1.507607 m 0.250592,1.148827 c 0.222947,-0.01585 0.38597,-0.06981 0.489069,-0.161867 0.104397,-0.09204 0.158048,-0.225938 0.160953,-0.401694 9.65e-4,-0.05859 -0.0078,-0.120588 -0.02623,-0.186005 -0.01717,-0.06409 -0.04939,-0.12388 -0.09666,-0.179355 -0.04727,-0.05548 -0.112252,-0.10278 -0.194949,-0.141911 -0.0814,-0.03911 -0.185846,-0.06232 -0.313346,-0.06964 l -0.01884,1.14047" + inkscape:connector-curvature="0" + id="path3913" /> + <path + d="m 77.670156,51.238318 c -0.128928,-0.07716 -0.217647,-0.172223 -0.266159,-0.285179 -0.04863,-0.111663 -0.06572,-0.246591 -0.05125,-0.404785 0.0243,-0.265819 0.131669,-0.453438 0.322108,-0.562857 0.19032,-0.108124 0.467015,-0.14559 0.830085,-0.1124 0.733918,0.06709 1.077288,0.358674 1.030113,0.874752 -0.01458,0.15949 -0.05591,0.289732 -0.123975,0.390727 -0.06807,0.100992 -0.168607,0.178097 -0.301607,0.231316 l -3.55e-4,0.0039 c 0.01297,0.0012 0.03312,0.0024 0.06047,0.0036 0.02853,0.0026 0.05776,0.0046 0.0877,0.0061 0.03112,0.0028 0.06029,0.0055 0.08753,0.008 0.02723,0.0025 0.04668,0.0043 0.05835,0.0053 l 0.814961,0.0745 -0.032,0.350103 -2.452664,-0.224209 c -0.05057,-0.0046 -0.0992,-0.0091 -0.145876,-0.01333 -0.0468,-0.003 -0.08971,-0.0056 -0.128726,-0.0078 -0.03902,-0.0023 -0.07285,-0.004 -0.101497,-0.0054 -0.02735,-0.0012 -0.04692,-0.0017 -0.05871,-0.0014 l 0.03058,-0.334542 c 0.0132,-0.0014 0.03159,-0.0023 0.05517,-0.0028 0.02475,9.54e-4 0.05281,0.0016 0.08417,0.0018 0.03124,0.0015 0.06377,0.0032 0.09761,0.005 0.03513,0.0019 0.06955,0.0044 0.103264,0.0075 l 7.11e-4,-0.0078 m 0.812846,-0.996547 c -0.145229,-0.01328 -0.270539,-0.01558 -0.375932,-0.0069 -0.105395,0.0087 -0.193642,0.03002 -0.264743,0.06406 -0.06981,0.03415 -0.123113,0.08093 -0.159923,0.140321 -0.03681,0.0594 -0.0593,0.133828 -0.06748,0.2233 -0.0084,0.09206 -9.13e-4,0.174468 0.02251,0.247216 0.0233,0.07404 0.06589,0.137427 0.127751,0.190154 0.06304,0.05414 0.147248,0.09845 0.25262,0.132924 0.105371,0.03447 0.235858,0.05882 0.39146,0.07305 0.149117,0.01363 0.27602,0.01281 0.380711,-0.0025 0.105985,-0.01516 0.192939,-0.04382 0.260864,-0.08599 0.06792,-0.04217 0.118698,-0.09702 0.152331,-0.16455 0.03481,-0.06612 0.05636,-0.144559 0.06466,-0.235325 0.0078,-0.08558 -3.34e-4,-0.160856 -0.02447,-0.225821 -0.02414,-0.06497 -0.06737,-0.121221 -0.129707,-0.168759 -0.06234,-0.04754 -0.145723,-0.08654 -0.250152,-0.117008 -0.103254,-0.02905 -0.230088,-0.05045 -0.380501,-0.0642" + inkscape:connector-curvature="0" + id="path3915" /> + <path + d="m 78.791939,53.959052 -1.825621,-0.342233 0.06478,-0.345543 1.825621,0.342232 0.0547,-0.291792 0.251479,0.04714 -0.0547,0.291792 0.234202,0.0439 c 0.07551,0.01415 0.143934,0.03427 0.205287,0.06034 0.06263,0.02631 0.11414,0.06246 0.154538,0.108456 0.04143,0.04751 0.06947,0.106418 0.08411,0.176727 0.01592,0.07055 0.01416,0.157651 -0.0053,0.261315 -0.0077,0.04095 -0.01752,0.08282 -0.02951,0.12562 -0.01224,0.04407 -0.02532,0.08203 -0.03923,0.113862 l -0.262997,-0.0493 c 0.0079,-0.02104 0.01591,-0.04603 0.02399,-0.07499 0.0091,-0.02744 0.01583,-0.05267 0.02015,-0.07571 0.0096,-0.05119 0.01047,-0.09475 0.0026,-0.130657 -0.0081,-0.03464 -0.02376,-0.06407 -0.04704,-0.0883 -0.02224,-0.02272 -0.05183,-0.04151 -0.08879,-0.05639 -0.0372,-0.0136 -0.08075,-0.02507 -0.130659,-0.03443 l -0.18621,-0.03491 -0.07593,0.405054 -0.251478,-0.04714 0.07593,-0.405054" + inkscape:connector-curvature="0" + id="path3917" /> + <path + d="m 77.441728,56.26852 c -0.358999,-0.08869 -0.606835,-0.233741 -0.743508,-0.435155 -0.136672,-0.201419 -0.167847,-0.452553 -0.09353,-0.753403 0.03529,-0.142842 0.08832,-0.265206 0.159089,-0.367091 0.07077,-0.101886 0.160081,-0.181086 0.267928,-0.237599 0.107534,-0.05525 0.232818,-0.08734 0.375852,-0.09626 0.143985,-0.0073 0.30636,0.0113 0.487124,0.05596 0.707885,0.174875 0.9861,0.568852 0.834647,1.181933 -0.03935,0.159273 -0.09535,0.290961 -0.168011,0.395064 -0.07297,0.105364 -0.162759,0.183776 -0.269355,0.235235 -0.106911,0.05272 -0.231103,0.08038 -0.372574,0.08299 -0.141473,0.0026 -0.300695,-0.01795 -0.477666,-0.06167 m 0.08853,-0.358367 c 0.159274,0.03934 0.293861,0.05918 0.403762,0.05951 0.109587,0.0016 0.201284,-0.01399 0.275092,-0.04672 0.07349,-0.03147 0.13068,-0.07837 0.171562,-0.140695 0.04214,-0.06202 0.07383,-0.136003 0.09507,-0.221959 0.02155,-0.08722 0.02779,-0.169507 0.01873,-0.246852 -0.0081,-0.07577 -0.03767,-0.146113 -0.0887,-0.211025 -0.04976,-0.0646 -0.123192,-0.122978 -0.220288,-0.17513 -0.09741,-0.05089 -0.223855,-0.09554 -0.379336,-0.133948 -0.159276,-0.03935 -0.294807,-0.05808 -0.406595,-0.05618 -0.110526,0.0022 -0.202691,0.01967 -0.276498,0.05241 -0.07412,0.034 -0.131938,0.08074 -0.173458,0.140226 -0.04183,0.06075 -0.07243,0.130312 -0.09179,0.208686 -0.02155,0.08722 -0.02906,0.169192 -0.02253,0.245915 0.0078,0.07703 0.03657,0.14785 0.08633,0.212453 0.04976,0.0646 0.123822,0.123132 0.222183,0.175598 0.09836,0.05246 0.227178,0.09837 0.386453,0.137718" + inkscape:connector-curvature="0" + id="path3919" /> + <path + d="m 76.277382,56.441011 1.547231,0.483758 c 0.04225,0.01321 0.08532,0.02599 0.129208,0.03835 0.04474,0.01399 0.08781,0.02677 0.129208,0.03835 0.0414,0.01158 0.08031,0.02238 0.116742,0.03241 0.03643,0.01002 0.06913,0.01888 0.0981,0.02658 l -0.09908,0.316902 c -0.02897,-0.0077 -0.0623,-0.01675 -0.09997,-0.02716 -0.03682,-0.0088 -0.07468,-0.01858 -0.113597,-0.02938 -0.0393,-0.0096 -0.07697,-0.01998 -0.113013,-0.03124 -0.03519,-0.0096 -0.06521,-0.01834 -0.09006,-0.02611 l -0.0023,0.0075 c 0.06967,0.0477 0.128383,0.09334 0.176149,0.13693 0.04862,0.04521 0.08531,0.09147 0.110085,0.138783 0.02601,0.0477 0.03995,0.09912 0.04181,0.154271 0.0031,0.05554 -0.0064,0.118724 -0.02857,0.189563 -0.0085,0.02734 -0.01919,0.05266 -0.03194,0.07596 -0.0115,0.02369 -0.02125,0.04178 -0.02925,0.05429 l -0.307582,-0.09617 c 0.01321,-0.02043 0.02572,-0.04517 0.03753,-0.07421 0.01305,-0.02866 0.02541,-0.06163 0.03707,-0.09891 0.02409,-0.07705 0.02728,-0.148358 0.0096,-0.213917 -0.01809,-0.06432 -0.05276,-0.123591 -0.104021,-0.177815 -0.0504,-0.0526 -0.115956,-0.100376 -0.196654,-0.143341 -0.07946,-0.04258 -0.169517,-0.0796 -0.270179,-0.111077 l -1.051371,-0.328722 0.104911,-0.335544" + inkscape:connector-curvature="0" + id="path3921" /> + <path + d="m 77.57706,60.103407 -0.941955,-0.400182 -0.600272,1.412932 -0.284025,-0.120665 0.600273,-1.412932 -1.026443,-0.436076 0.145868,-0.343346 2.532851,1.076061 -0.764469,1.799421 -0.28043,-0.119138 0.618602,-1.456075" + inkscape:connector-curvature="0" + id="path3923" /> + <path + d="m 73.672921,62.572089 0.858474,0.09708 0.58473,-1.109222 -0.564288,-0.655144 0.180337,-0.342096 1.910706,2.27677 -0.197642,0.374923 -2.949922,-0.305396 0.177605,-0.336913 m 2.136088,0.245098 c 0.05579,0.0059 0.111848,0.01259 0.168183,0.02021 0.05572,0.0088 0.105932,0.01684 0.150624,0.02421 0.04584,0.008 0.08386,0.01403 0.114059,0.01818 0.03074,0.0059 0.0493,0.0098 0.05566,0.01168 -0.0045,-0.0053 -0.01794,-0.01903 -0.04018,-0.04105 -0.02224,-0.02203 -0.0493,-0.05028 -0.08118,-0.08474 -0.03248,-0.03332 -0.06779,-0.07106 -0.105902,-0.113231 -0.03873,-0.04102 -0.07657,-0.08232 -0.113535,-0.123879 l -0.63601,-0.732695 -0.479988,0.91053 0.968262,0.110794" + inkscape:connector-curvature="0" + id="path3925" /> + <path + d="m 73.310171,63.196101 2.308254,1.498402 -1.136829,1.751259 -0.255563,-0.165899 0.93371,-1.438358 -0.740476,-0.48068 -0.869903,1.340065 -0.252286,-0.163771 0.869903,-1.340065 -0.804367,-0.522155 -0.977311,1.505526 -0.255563,-0.165899 1.180431,-1.818425" + inkscape:connector-curvature="0" + id="path3927" /> + <path + d="m 70.724956,66.823317 2.751648,0.30052 c -0.05164,-0.03757 -0.103165,-0.07422 -0.154586,-0.109958 -0.04347,-0.0311 -0.08909,-0.06473 -0.13685,-0.100896 -0.04755,-0.03434 -0.08919,-0.06565 -0.124918,-0.09394 l -1.433179,-1.13492 0.206129,-0.260299 2.157423,1.708441 -0.26918,0.339921 -2.773597,-0.297971 c 0.05244,0.03655 0.104887,0.07309 0.15733,0.10964 0.04449,0.03191 0.09255,0.06664 0.144187,0.104215 0.05266,0.03837 0.101951,0.07575 0.147886,0.112127 l 1.414804,1.120369 -0.208553,0.263361 -2.157424,-1.708441 0.27888,-0.35217" + inkscape:connector-curvature="0" + id="path3929" /> + <path + d="m 68.636859,69.108388 1.509272,-1.588823 0.202497,0.192358 0.417682,2.708113 1.055952,-1.11161 0.220906,0.209845 -1.347853,1.418896 -0.196833,-0.186978 -0.423345,-2.713493 -1.217372,1.281538 -0.220906,-0.209846" + inkscape:connector-curvature="0" + id="path3931" /> + <path + d="m 66.845397,70.716316 0.76893,0.39389 0.938663,-0.831379 -0.296674,-0.81217 0.289494,-0.256407 0.983929,2.804704 -0.317274,0.281012 -2.652176,-1.327128 0.285108,-0.252522 m 1.912028,0.983409 c 0.05013,0.02517 0.100201,0.05127 0.150218,0.07828 0.04904,0.02788 0.09317,0.05315 0.132381,0.07582 0.04008,0.02364 0.07351,0.04273 0.100299,0.05727 0.02668,0.01637 0.04266,0.02657 0.04796,0.03058 -0.0024,-0.0066 -0.01007,-0.02413 -0.0231,-0.05259 -0.01303,-0.02846 -0.02838,-0.06445 -0.04603,-0.107944 -0.01863,-0.04264 -0.03833,-0.09041 -0.05911,-0.143327 -0.02175,-0.05205 -0.04258,-0.104047 -0.06249,-0.155984 l -0.336401,-0.910045 -0.770522,0.682456 0.866806,0.445481" + inkscape:connector-curvature="0" + id="path3933" /> + </g> + </g> + <g + id="layer4" + style="display:inline"> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 1 1 -27.274118,0 13.637059,13.637059 0 1 1 27.274118,0 z" + transform="matrix(1.0266143,0,0,1.0266143,-0.999999,0.7783622)" + id="path3757" + style="fill:#000000;fill-opacity:1;stroke:none" /> + <path + d="M 47.5,33 C 39.491871,33 33,39.491871 33,47.5 33,55.508129 39.491871,62 47.5,62 c 0.08504,0 0.165309,0.0015 0.25,0 C 40.133878,61.866031 34,55.648102 34,48 c 0,-7.731986 6.268014,-14 14,-14 7.648102,0 13.866031,6.133878 14,13.75 0.0015,-0.08469 0,-0.164961 0,-0.25 C 62,39.491871 55.508129,33 47.5,33 z" + inkscape:connector-curvature="0" + id="path3760" + style="opacity:0.6;fill:#000000;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 1 1 -27.274118,0 13.637059,13.637059 0 1 1 27.274118,0 z" + transform="matrix(1.0266143,0,0,1.0266143,-0.999999,0.778362)" + id="path2907" + style="fill:url(#radialGradient3687);fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 1 1 -27.274118,0 13.637059,13.637059 0 1 1 27.274118,0 z" + transform="matrix(0,0.97161711,-0.97161711,0,92.69191,1.6250011)" + id="path3705" + style="fill:none;stroke:url(#linearGradient3733);stroke-width:0.514606;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter3774)" /> + <path + d="m 41.34375,47.375 c 0.07082,-0.767299 0.285421,-1.486362 0.59375,-2.15625 L 37.34375,42.8125 c -0.603997,1.243084 -1.018186,2.621977 -1.15625,4.0625 l 5.15625,0.5 z m 1.375,-3.4375 c 1.071033,-1.389071 2.667628,-2.34897 4.5,-2.5625 L 46.625,36.21875 c -3.598468,0.417087 -6.654118,2.435762 -8.53125,5.3125 l 4.625,2.40625 z" + inkscape:connector-curvature="0" + id="path3735" + style="opacity:0.6;fill:#ffffff;fill-opacity:1;stroke:none" /> + <path + d="m 50.708204,52 a 9.7082043,6 0 1 1 -19.416408,0 9.7082043,6 0 1 1 19.416408,0 z" + transform="matrix(0.58268801,-0.58268801,0.58268801,0.58268801,-0.74355667,46.935862)" + id="path3759" + style="opacity:0.4314516;fill:url(#linearGradient3767);fill-opacity:1;stroke:none" /> + <path + d="m 50.708204,52 a 9.7082043,6 0 1 1 -19.416408,0 9.7082043,6 0 1 1 19.416408,0 z" + transform="matrix(0.15076894,-0.15076894,0.15076894,0.15076894,37.387737,49.649792)" + id="path3769" + style="opacity:0.3;fill:url(#linearGradient3771);fill-opacity:1;stroke:none" /> + <path + d="m 50.708204,52 a 9.7082043,6 0 1 1 -19.416408,0 9.7082043,6 0 1 1 19.416408,0 z" + transform="matrix(-0.10757707,0.10757707,-0.10757707,-0.10757707,55.999137,47.076819)" + id="path3773" + style="opacity:0.3;fill:url(#linearGradient3775);fill-opacity:1;stroke:none" /> + <path + d="m 50.708204,52 a 9.7082043,6 0 1 1 -19.416408,0 9.7082043,6 0 1 1 19.416408,0 z" + transform="matrix(-0.19358861,0.19358861,-0.19358861,-0.19358861,59.194255,43.21899)" + id="path3777" + style="opacity:0.4314516;fill:url(#linearGradient3779);fill-opacity:1;stroke:none" /> + <path + d="m 50.708204,52 a 9.7082043,6 0 1 1 -19.416408,0 9.7082043,6 0 1 1 19.416408,0 z" + transform="matrix(0.08968638,-0.08968638,0.08968638,0.08968638,40.497472,47.750757)" + id="path3789" + style="opacity:0.6;fill:url(#linearGradient3791);fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 1 1 -27.274118,0 13.637059,13.637059 0 1 1 27.274118,0 z" + transform="matrix(1.0266143,0,0,1.0266143,69.000001,0.7783622)" + id="path3779" + style="opacity:0.6;fill:#ff00ff;fill-opacity:1;stroke:none;display:inline" /> + <path + d="m 48,32 c -8.836556,0 -16,7.163444 -16,16 0,8.836556 7.163444,16 16,16 8.836556,0 16,-7.163444 16,-16 0,-8.836556 -7.163444,-16 -16,-16 z m 0,1.5 c 8.008129,0 14.5,6.491871 14.5,14.5 0,8.008129 -6.491871,14.5 -14.5,14.5 -8.008129,0 -14.5,-6.491871 -14.5,-14.5 0,-8.008129 6.491871,-14.5 14.5,-14.5 z" + inkscape:connector-curvature="0" + id="path3806" + style="opacity:0.7;fill:url(#linearGradient3817);fill-opacity:1;stroke:none;display:inline" /> + </g> + <g + id="layer6" + style="display:inline"> + <g + clip-path="url(#clipPath3798)" + id="g3786" + style="opacity:0.4;display:inline;filter:url(#filter3833)"> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(1.0266143,0,0,1.0266143,-0.9999987,0.7783622)" + id="path3756" + style="fill:#d40000;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(0.72592593,0.72592593,-0.72592593,0.72592593,46.742509,-20.038972)" + id="path3772" + style="fill:#d42aff;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(0,1.0266143,-1.0266143,0,95.221638,-0.99999877)" + id="path3774" + style="fill:#6600ff;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(-0.72592593,0.72592593,-0.72592593,-0.72592593,116.03897,46.742509)" + id="path3776" + style="fill:#2a7fff;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(-1.0266143,0,0,-1.0266143,96.999997,95.221637)" + id="path3778" + style="fill:#5fd3bc;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(-0.72592593,-0.72592593,0.72592593,-0.72592593,49.25749,116.03897)" + id="path3780" + style="fill:#55d400;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(0,-1.0266143,1.0266143,0,0.77836254,96.999997)" + id="path3782" + style="fill:#ffcc00;fill-opacity:1;stroke:none" /> + <path + d="m 61.366765,45.997448 a 13.637059,13.637059 0 0 1 -3.994202,9.642857 l -9.642857,-9.642857 z" + transform="matrix(0.72592593,-0.72592593,0.72592593,0.72592593,-20.03897,49.25749)" + id="path3784" + style="fill:#ff6600;fill-opacity:1;stroke:none" /> + </g> + <g + transform="translate(0,-50)" + id="g3957" + style="opacity:0.8;filter:url(#filter3987)"> + <path + d="m 61.53125,94.375 -0.96875,0.25 C 60.849921,95.699342 61,96.835019 61,98 c 0,4.80784 -2.619633,9.00086 -6.5,11.25 l 0.5,0.875 c 5.487553,-3.16824 8.171252,-9.62943 6.53125,-15.75 z" + inkscape:connector-curvature="0" + id="path3726" + style="opacity:0.8;fill:url(#linearGradient3967);fill-opacity:1;stroke:none" /> + <path + d="m 59.25,104.5 c -2.249137,3.88037 -6.442164,6.5 -11.25,6.5 -1.164981,0 -2.300658,-0.15008 -3.375,-0.4375 l -0.25,0.96875 c 6.120569,1.64 12.58176,-1.0437 15.75,-6.53125 l -0.875,-0.5 z" + inkscape:connector-curvature="0" + id="path3728" + style="opacity:0.8;fill:url(#linearGradient3969);fill-opacity:1;stroke:none" /> + <path + d="m 36.75,104.5 -0.875,0.5 c 3.16824,5.48755 9.629431,8.17125 15.75,6.53125 l -0.25,-0.96875 C 50.300658,110.84992 49.164981,111 48,111 c -4.807836,0 -9.000863,-2.61963 -11.25,-6.5 z" + inkscape:connector-curvature="0" + id="path3730" + style="fill:url(#linearGradient3971);fill-opacity:1;stroke:none" /> + <path + d="m 34.46875,94.375 c -1.640002,6.12057 1.043697,12.58176 6.53125,15.75 l 0.5,-0.875 C 37.619633,107.00086 35,102.80784 35,98 c 0,-1.164981 0.150079,-2.300658 0.4375,-3.375 l -0.96875,-0.25 z" + inkscape:connector-curvature="0" + id="path3732" + style="opacity:0.9;fill:url(#linearGradient3973);fill-opacity:1;stroke:none" /> + <path + d="m 41,85.875 c -5.487553,3.16824 -8.171252,9.629431 -6.53125,15.75 l 0.96875,-0.25 C 35.150079,100.30066 35,99.164981 35,98 35,93.192164 37.619633,88.999137 41.5,86.75 L 41,85.875 z" + inkscape:connector-curvature="0" + id="path3734" + style="fill:url(#linearGradient3975);fill-opacity:1;stroke:none" /> + <path + d="M 48.15625,84 C 43.183834,83.93941 38.449195,86.541364 35.875,91 l 0.875,0.5 C 38.999137,87.619633 43.192164,85 48,85 c 1.164981,0 2.300658,0.150079 3.375,0.4375 l 0.25,-0.96875 C 50.477393,84.16125 49.303731,84.013982 48.15625,84 z" + inkscape:connector-curvature="0" + id="path3736" + style="fill:url(#linearGradient3977);fill-opacity:1;stroke:none" /> + <path + d="m 47.84375,84 c -1.147481,0.01398 -2.321143,0.16125 -3.46875,0.46875 l 0.25,0.96875 C 45.699342,85.150079 46.835019,85 48,85 c 4.807836,0 9.000863,2.619633 11.25,6.5 L 60.125,91 C 57.550805,86.541363 52.816166,83.939411 47.84375,84 z" + inkscape:connector-curvature="0" + id="path3738" + style="fill:url(#linearGradient3979);fill-opacity:1;stroke:none" /> + <path + d="m 55,85.875 -0.5,0.875 c 3.880367,2.249137 6.5,6.442164 6.5,11.25 0,1.164981 -0.150079,2.30066 -0.4375,3.375 l 0.96875,0.25 C 63.171252,95.504431 60.487553,89.04324 55,85.875 z" + inkscape:connector-curvature="0" + id="path3740" + style="opacity:0.9;fill:url(#linearGradient3981);fill-opacity:1;stroke:none" /> + </g> + <path + d="m 50.708204,52 a 9.7082043,6 0 1 1 -19.416408,0 9.7082043,6 0 1 1 19.416408,0 z" + transform="matrix(0.23287504,-0.23287504,0.23287504,0.23287504,33.266783,52.13527)" + id="path3793" + style="fill:url(#radialGradient3803);fill-opacity:1;stroke:none;display:inline" /> + </g> +</svg> diff --git a/rapid/glade3/photo24.png b/rapid/glade3/photo24.png Binary files differdeleted file mode 100644 index 53b2271..0000000 --- a/rapid/glade3/photo24.png +++ /dev/null diff --git a/rapid/glade3/photo66.png b/rapid/glade3/photo66.png Binary files differnew file mode 100644 index 0000000..1bef29f --- /dev/null +++ b/rapid/glade3/photo66.png diff --git a/rapid/glade3/photo_icon.png b/rapid/glade3/photo_icon.png Binary files differnew file mode 100644 index 0000000..52e22bc --- /dev/null +++ b/rapid/glade3/photo_icon.png diff --git a/rapid/glade3/photo_small.png b/rapid/glade3/photo_small.png Binary files differdeleted file mode 100644 index f44d380..0000000 --- a/rapid/glade3/photo_small.png +++ /dev/null diff --git a/rapid/glade3/photo_small_shadow.png b/rapid/glade3/photo_small_shadow.png Binary files differdeleted file mode 100644 index fe85cd9..0000000 --- a/rapid/glade3/photo_small_shadow.png +++ /dev/null diff --git a/rapid/glade3/rapid.glade b/rapid/glade3/prefs.ui index 163174b..9d1eb31 100644 --- a/rapid/glade3/rapid.glade +++ b/rapid/glade3/prefs.ui @@ -1,8 +1,19 @@ <?xml version="1.0" encoding="UTF-8"?> -<glade-interface> - <!-- interface-requires gtk+ 2.16 --> - <!-- interface-naming-policy toplevel-contextual --> - <widget class="GtkDialog" id="preferencesdialog"> +<interface> + <requires lib="gtk+" version="2.16"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkAdjustment" id="hour_adjustment"> + <property name="upper">23</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkAdjustment" id="minute_adjustment"> + <property name="upper">59</property> + <property name="step_increment">1</property> + <property name="page_increment">10</property> + </object> + <object class="GtkDialog" id="preferencesdialog"> + <property name="can_focus">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="border_width">5</property> <property name="title" translatable="yes">Preferences: Rapid Photo Downloader</property> @@ -11,18 +22,64 @@ <property name="default_height">500</property> <property name="icon">rapid-photo-downloader.svg</property> <property name="type_hint">dialog</property> - <signal name="destroy" handler="on_preferencesdialog_destroy"/> - <signal name="response" handler="on_response"/> + <signal name="destroy" handler="on_preferencesdialog_destroy" swapped="no"/> + <signal name="response" handler="on_preferencesdialog_response" swapped="no"/> <child internal-child="vbox"> - <widget class="GtkVBox" id="dialog-vbox2"> + <object class="GtkVBox" id="dialog-vbox2"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">2</property> + <child internal-child="action_area"> + <object class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">end</property> + <child> + <object class="GtkButton" id="help_button1"> + <property name="label">gtk-help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + <property name="secondary">True</property> + </packing> + </child> + <child> + <object class="GtkButton" id="close_button"> + <property name="label">gtk-close</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> + <property name="use_stock">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> <child> - <widget class="GtkHBox" id="hbox3"> + <object class="GtkHBox" id="hbox7"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">2</property> <child> - <widget class="GtkScrolledWindow" id="scrolled_window"> + <object class="GtkScrolledWindow" id="scrolled_window"> <property name="visible">True</property> <property name="can_focus">True</property> <property name="resize_mode">queue</property> @@ -30,74 +87,86 @@ <property name="vscrollbar_policy">automatic</property> <property name="shadow_type">in</property> <child> - <widget class="GtkTreeView" id="treeview"> + <object 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> + <signal name="cursor-changed" handler="on_treeview_cursor_changed" swapped="no"/> + </object> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">5</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkNotebook" id="notebook"> + <object 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"> + <object class="GtkVBox" id="folder_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox6"> + <object class="GtkVBox" id="vbox6"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox4"> + <object class="GtkHBox" id="hbox8"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image2"> + <object class="GtkImage" id="image2"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">gtk-directory</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label2"> + <object class="GtkLabel" id="label4"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Photo Download Folders</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator1"> + <object class="GtkHSeparator" id="hseparator1"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -105,31 +174,36 @@ </packing> </child> <child> - <widget class="GtkHBox" id="hbox9"> + <object class="GtkHBox" id="hbox9"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label16"> + <object class="GtkLabel" id="label16"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="download_folder_table"> + <object class="GtkTable" id="download_folder_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">7</property> <property name="n_columns">3</property> <child> - <widget class="GtkLabel" id="example_photo_download_path_label"> + <object class="GtkLabel" id="example_photo_download_path_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><i>Example: /home/user/Pictures</i></property> <property name="use_markup">True</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -138,12 +212,13 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label8"> + <object class="GtkLabel" id="label8"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Download Subfolders</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">3</property> <property name="top_attach">3</property> @@ -152,11 +227,12 @@ </packing> </child> <child> - <widget class="GtkLabel" id="lblPhotos1"> + <object class="GtkLabel" id="lblPhotos1"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Download folder:</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -167,14 +243,15 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label7"> + <object class="GtkLabel" id="label7"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -184,25 +261,27 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label5"> + <object class="GtkLabel" id="label5"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Download Folder</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">3</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="photo_subfolder_warning_label"> + <object class="GtkLabel" id="photo_subfolder_warning_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="yalign">0</property> <property name="wrap">True</property> <property name="wrap_mode">word-char</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -212,12 +291,13 @@ </packing> </child> <child> - <widget class="GtkVBox" id="subfolder_vbox"> + <object class="GtkVBox" id="subfolder_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> <placeholder/> </child> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -244,88 +324,105 @@ <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label23"> + <object class="GtkLabel" id="label23"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="menu_label">Download Folders</property> </packing> </child> - <child> - <widget class="GtkLabel" id="download_label"> + <child type="tab"> + <object class="GtkLabel" id="download_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Photo Folders</property> - </widget> + </object> <packing> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="rename_tab"> + <object class="GtkVBox" id="rename_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox7"> + <object class="GtkVBox" id="vbox7"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox5"> + <object class="GtkHBox" id="hbox10"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image3"> + <object class="GtkImage" id="image3"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">gtk-convert</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label4"> + <object class="GtkLabel" id="label6"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Photo Rename</span> </property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator2"> + <object class="GtkHSeparator" id="hseparator2"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -333,70 +430,82 @@ </packing> </child> <child> - <widget class="GtkHBox" id="hbox12"> + <object class="GtkHBox" id="hbox12"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label24"> + <object class="GtkLabel" id="label24"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkVBox" id="rename_vbox"> + <object class="GtkVBox" id="rename_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label42"> + <object class="GtkLabel" id="label42"> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Photo Rename</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkScrolledWindow" id="rename_scrolledwindow"> + <object 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"> + <object class="GtkViewport" id="viewport2"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="resize_mode">queue</property> <property name="shadow_type">none</property> <child> - <widget class="GtkVBox" id="rename_table_vbox"> + <object class="GtkVBox" id="rename_table_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> <placeholder/> </child> - </widget> + </object> </child> - </widget> + </object> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkTable" id="rename_example_table"> + <object class="GtkTable" id="rename_example_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">3</property> <property name="n_columns">3</property> <child> - <widget class="GtkLabel" id="label17"> + <object class="GtkLabel" id="label17"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"> </property> - </widget> + </object> <packing> <property name="top_attach">2</property> <property name="bottom_attach">3</property> @@ -404,10 +513,11 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label15"> + <object class="GtkLabel" id="label15"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"> </property> - </widget> + </object> <packing> <property name="top_attach">1</property> <property name="bottom_attach">2</property> @@ -416,13 +526,14 @@ </packing> </child> <child> - <widget class="GtkLabel" id="new_name_label"> + <object class="GtkLabel" id="new_name_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="yalign">0</property> <property name="label">translators please ignore this</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -432,11 +543,12 @@ </packing> </child> <child> - <widget class="GtkLabel" id="original_name_label"> + <object class="GtkLabel" id="original_name_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label">translators please ignore this</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -446,13 +558,14 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label21"> + <object class="GtkLabel" id="label21"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -463,12 +576,13 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label20"> + <object class="GtkLabel" id="label20"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><i>Original:</i></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -479,109 +593,126 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label14"> + <object class="GtkLabel" id="label14"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Example</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">3</property> <property name="y_padding">12</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label25"> + <object class="GtkLabel" id="label25"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="menu_label">Rename</property> <property name="position">1</property> </packing> </child> - <child> - <widget class="GtkLabel" id="rename_label"> + <child type="tab"> + <object class="GtkLabel" id="rename_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Photo Rename</property> - </widget> + </object> <packing> <property name="position">1</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="folder_tab1"> + <object class="GtkVBox" id="folder_tab1"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox12"> + <object class="GtkVBox" id="vbox12"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox8"> + <object class="GtkHBox" id="hbox11"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image5"> + <object class="GtkImage" id="image5"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">gtk-directory</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label46"> + <object class="GtkLabel" id="label46"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Video Download Folders</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator8"> + <object class="GtkHSeparator" id="hseparator8"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -589,21 +720,25 @@ </packing> </child> <child> - <widget class="GtkHBox" id="folder_videos_cannot_be_downloaded_hbox"> + <object class="GtkHBox" id="folder_videos_cannot_be_downloaded_hbox"> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="folder_videos_cannot_be_downloaded_label"> + <object class="GtkLabel" id="folder_videos_cannot_be_downloaded_label"> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="xpad">12</property> <property name="ypad">10</property> <property name="label" translatable="yes">Sorry, video downloading functionality disabled. To download videos, please install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for python.</property> <property name="use_markup">True</property> <property name="wrap">True</property> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -611,29 +746,34 @@ </packing> </child> <child> - <widget class="GtkHBox" id="video_folders_hbox"> + <object class="GtkHBox" id="video_folders_hbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label57"> + <object class="GtkLabel" id="label57"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="video_download_folder_table"> + <object class="GtkTable" id="video_download_folder_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">7</property> <property name="n_columns">3</property> <child> - <widget class="GtkLabel" id="lblPhotos2"> + <object class="GtkLabel" id="lblPhotos2"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Download folder:</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -644,14 +784,15 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label59"> + <object class="GtkLabel" id="label59"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="ypad">12</property> <property name="label" translatable="yes">Choose the download folder. Subfolders for the downloaded videos 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> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -661,24 +802,26 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label61"> + <object class="GtkLabel" id="label61"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Download Folder</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">3</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkLabel" id="label62"> + <object class="GtkLabel" id="label62"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Download Subfolders</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">3</property> <property name="top_attach">3</property> @@ -687,13 +830,14 @@ </packing> </child> <child> - <widget class="GtkLabel" id="example_video_download_path_label"> + <object class="GtkLabel" id="example_video_download_path_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><i>Example: /home/user/Pictures</i></property> <property name="use_markup">True</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -702,13 +846,14 @@ </packing> </child> <child> - <widget class="GtkLabel" id="video_subfolder_warning_label"> + <object class="GtkLabel" id="video_subfolder_warning_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="yalign">0</property> <property name="wrap">True</property> <property name="wrap_mode">word-char</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -718,12 +863,13 @@ </packing> </child> <child> - <widget class="GtkVBox" id="video_subfolder_vbox"> + <object class="GtkVBox" id="video_subfolder_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> <placeholder/> </child> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -750,89 +896,106 @@ <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label63"> + <object class="GtkLabel" id="label63"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="position">2</property> </packing> </child> - <child> - <widget class="GtkLabel" id="video_download_folder"> + <child type="tab"> + <object class="GtkLabel" id="video_download_folder"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Video Folders</property> - </widget> + </object> <packing> <property name="position">2</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="video_rename_tab"> + <object class="GtkVBox" id="video_rename_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox10"> + <object class="GtkVBox" id="vbox10"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox1"> + <object class="GtkHBox" id="hbox13"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image1"> + <object class="GtkImage" id="image1"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">gtk-convert</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label32"> + <object class="GtkLabel" id="label32"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Video Rename</span> </property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator3"> + <object class="GtkHSeparator" id="hseparator4"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -840,29 +1003,34 @@ </packing> </child> <child> - <widget class="GtkHBox" id="hbox6"> + <object class="GtkHBox" id="hbox14"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label44"> + <object class="GtkLabel" id="label44"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkVBox" id="rename_vbox1"> + <object class="GtkVBox" id="rename_vbox1"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="videos_cannot_be_downloaded_label"> + <object class="GtkLabel" id="videos_cannot_be_downloaded_label"> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Sorry, video downloading functionality disabled. To download videos, please install the <i>hachoir metadata</i> and <i>kaa metadata</i> packages for python.</property> <property name="use_markup">True</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -870,42 +1038,48 @@ </packing> </child> <child> - <widget class="GtkScrolledWindow" id="video_rename_scrolledwindow"> + <object class="GtkScrolledWindow" id="video_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="viewport1"> + <object class="GtkViewport" id="viewport1"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="resize_mode">queue</property> <property name="shadow_type">none</property> <child> - <widget class="GtkVBox" id="video_rename_table_vbox"> + <object class="GtkVBox" id="video_rename_table_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> <placeholder/> </child> - </widget> + </object> </child> - </widget> + </object> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkTable" id="video_rename_example_table"> + <object class="GtkTable" id="video_rename_example_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">3</property> <property name="n_columns">3</property> <child> - <widget class="GtkLabel" id="label55"> + <object class="GtkLabel" id="label55"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"> </property> - </widget> + </object> <packing> <property name="top_attach">2</property> <property name="bottom_attach">3</property> @@ -913,10 +1087,11 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label56"> + <object class="GtkLabel" id="label56"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"> </property> - </widget> + </object> <packing> <property name="top_attach">1</property> <property name="bottom_attach">2</property> @@ -925,13 +1100,14 @@ </packing> </child> <child> - <widget class="GtkLabel" id="video_new_name_label"> + <object class="GtkLabel" id="video_new_name_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="yalign">0</property> <property name="label">translators please ignore this</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -941,11 +1117,12 @@ </packing> </child> <child> - <widget class="GtkLabel" id="video_original_name_label"> + <object class="GtkLabel" id="video_original_name_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label">translators please ignore this</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -955,13 +1132,14 @@ </packing> </child> <child> - <widget class="GtkLabel" id="new_video_filename_label"> + <object class="GtkLabel" id="new_video_filename_label"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -972,12 +1150,13 @@ </packing> </child> <child> - <widget class="GtkLabel" id="original_video_filename_label"> + <object class="GtkLabel" id="original_video_filename_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><i>Original:</i></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -988,107 +1167,125 @@ </packing> </child> <child> - <widget class="GtkLabel" id="example_video_filename_label"> + <object class="GtkLabel" id="example_video_filename_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Example</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">3</property> <property name="y_padding">12</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label60"> + <object class="GtkLabel" id="label60"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">3</property> </packing> </child> - <child> - <widget class="GtkLabel" id="video_rename_label"> + <child type="tab"> + <object class="GtkLabel" id="video_rename_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Video Rename</property> - </widget> + </object> <packing> <property name="position">3</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="rename_options_tab"> + <object class="GtkVBox" id="rename_options_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox14"> + <object class="GtkVBox" id="vbox14"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox18"> + <object class="GtkHBox" id="hbox18"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image7"> + <object class="GtkImage" id="image7"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="icon_name">input-keyboard</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label10"> + <object class="GtkLabel" id="label10"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Rename Options</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator4"> + <object class="GtkHSeparator" id="hseparator5"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1096,123 +1293,155 @@ </packing> </child> <child> - <widget class="GtkVBox" id="reame_options_vbox"> + <object class="GtkVBox" id="reame_options_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="sequence_number_label"> + <object class="GtkLabel" id="sequence_number_label"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHBox" id="sequence_number_hbox"> + <object class="GtkHBox" id="sequence_number_hbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="spacer_seq_label"> + <object class="GtkLabel" id="spacer_seq_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xpad">12</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkVBox" id="seq_vbox"> + <object class="GtkVBox" id="seq_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label47"> + <object class="GtkLabel" id="label47"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox23"> + <object class="GtkHBox" id="hbox23"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkVBox" id="vbox1"> + <object class="GtkVBox" id="vbox3"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkLabel" id="label49"> + <object class="GtkLabel" id="label49"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Day start:</property> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label51"> + <object class="GtkLabel" id="label51"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Downloads today:</property> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label52"> + <object class="GtkLabel" id="label52"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Stored number:</property> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label54"> + <object class="GtkLabel" id="label54"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xpad">6</property> <property name="label" translatable="yes"> </property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkVBox" id="sequence_vbox"> + <object class="GtkVBox" id="sequence_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkHBox" id="hbox22"> + <object class="GtkHBox" id="hbox22"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkSpinButton" id="hour_spinbutton"> + <object class="GtkSpinButton" id="hour_spinbutton"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="max_length">2</property> + <property name="invisible_char">•</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="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> + <property name="adjustment">hour_adjustment</property> <property name="numeric">True</property> - <signal name="value_changed" handler="on_hour_spinbutton_value_changed"/> - </widget> + <signal name="value-changed" handler="on_hour_spinbutton_value_changed" swapped="no"/> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1220,10 +1449,11 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label50"> + <object class="GtkLabel" id="label50"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">:</property> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1231,16 +1461,22 @@ </packing> </child> <child> - <widget class="GtkSpinButton" id="minute_spinbutton"> + <object class="GtkSpinButton" id="minute_spinbutton"> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="max_length">2</property> + <property name="invisible_char">•</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="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> + <property name="adjustment">minute_adjustment</property> <property name="numeric">True</property> - <signal name="value_changed" handler="on_minute_spinbutton_value_changed"/> - </widget> + <signal name="value-changed" handler="on_minute_spinbutton_value_changed" swapped="no"/> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1248,19 +1484,22 @@ </packing> </child> <child> - <widget class="GtkLabel" id="label53"> + <object class="GtkLabel" id="label53"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"> hh:mm</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">3</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> @@ -1270,200 +1509,237 @@ <child> <placeholder/> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkCheckButton" id="synchronize_raw_jpg_checkbutton"> + <object class="GtkCheckButton" id="synchronize_raw_jpg_checkbutton"> <property name="label" translatable="yes">Synchronize RAW + JPEG sequence numbers</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_synchronize_raw_jpg_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_synchronize_raw_jpg_checkbutton_toggled" swapped="no"/> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label48"> + <object class="GtkLabel" id="label48"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="compatibility_label"> + <object class="GtkLabel" id="compatibility_label"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">3</property> </packing> </child> <child> - <widget class="GtkHBox" id="compatibility_hbox"> + <object class="GtkHBox" id="compatibility_hbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="compatibility_spacer_label"> + <object class="GtkLabel" id="compatibility_spacer_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xpad">12</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="compatibility_table"> + <object class="GtkTable" id="compatibility_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">2</property> <property name="n_columns">2</property> <child> - <widget class="GtkLabel" id="label9"> + <object class="GtkLabel" id="label9"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Specify whether photo, video and folder names should have any characters removed that are not allowed by other operating systems.</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="right_attach">2</property> </packing> </child> <child> - <widget class="GtkCheckButton" id="strip_characters_checkbutton"> + <object 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_action_appearance">False</property> <property name="use_underline">True</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_strip_characters_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_strip_characters_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">2</property> <property name="top_attach">1</property> <property name="bottom_attach">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label33"> + <object class="GtkLabel" id="label33"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">4</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">4</property> </packing> </child> - <child> - <widget class="GtkLabel" id="rename_options_label"> + <child type="tab"> + <object class="GtkLabel" id="rename_options_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Rename Options</property> - </widget> + </object> <packing> <property name="position">4</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="job_codes_tab"> + <object class="GtkVBox" id="job_codes_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="job_codes_header_vbox"> + <object class="GtkVBox" id="job_codes_header_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox188"> + <object class="GtkHBox" id="hbox188"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image77"> + <object class="GtkImage" id="image77"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">rapid-photo-downloader-jobcode</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label1340"> + <object class="GtkLabel" id="label1340"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Job Codes</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator44"> + <object class="GtkHSeparator" id="hseparator44"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1471,75 +1747,86 @@ </packing> </child> <child> - <widget class="GtkVBox" id="job_codes_vbox"> + <object class="GtkVBox" id="job_codes_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkVBox" id="job_code_vbox"> + <object class="GtkVBox" id="job_code_vbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="job_code_label"> + <object class="GtkLabel" id="job_code_label"> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="xpad">12</property> <property name="label" translatable="yes"><b>Job Codes</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHBox" id="job_code_hbox"> + <object class="GtkHBox" id="job_code_hbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="job_code_spacer_label"> + <object class="GtkLabel" id="job_code_spacer_label"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkScrolledWindow" id="job_code_scrolledwindow"> + <object class="GtkScrolledWindow" id="job_code_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="shadow_type">in</property> <child> - <widget class="GtkTreeView" id="job_code_treeview"> + <object class="GtkTreeView" id="job_code_treeview"> <property name="width_request">250</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="headers_visible">False</property> <property name="rubber_banding">True</property> - </widget> + </object> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkHBox" id="job_code_button_hbox"> + <object class="GtkHBox" id="job_code_button_hbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkVButtonBox" id="job_code_vbuttonbox"> + <object class="GtkVButtonBox" id="job_code_vbuttonbox"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <property name="layout_style">start</property> <child> - <widget class="GtkButton" id="add_job_code_button"> + <object class="GtkButton" id="add_job_code_button"> <property name="label" translatable="yes">_Add...</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> - <signal name="clicked" handler="on_add_job_code_button_clicked"/> - </widget> + <signal name="clicked" handler="on_add_job_code_button_clicked" swapped="no"/> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1547,14 +1834,15 @@ </packing> </child> <child> - <widget class="GtkButton" id="remove_job_code_button"> + <object class="GtkButton" id="remove_job_code_button"> <property name="label">gtk-remove</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> <property name="use_stock">True</property> - <signal name="clicked" handler="on_remove_job_code_button_clicked"/> - </widget> + <signal name="clicked" handler="on_remove_job_code_button_clicked" swapped="no"/> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1562,112 +1850,133 @@ </packing> </child> <child> - <widget class="GtkButton" id="remove_all_job_code_button"> + <object class="GtkButton" id="remove_all_job_code_button"> <property name="label" translatable="yes" comments="The underscore after the C signifies that the l is the accelerator key. This is the standard 'Clear' button, but I needed to change the accelerator from the standard 'c' to 'l' because the close button also used 'c'">R_emove All</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> - <signal name="clicked" handler="on_remove_all_job_code_button_clicked"/> - </widget> + <signal name="clicked" handler="on_remove_all_job_code_button_clicked" swapped="no"/> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">5</property> </packing> </child> - <child> - <widget class="GtkLabel" id="job_codes_tab_label"> + <child type="tab"> + <object class="GtkLabel" id="job_codes_tab_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Job Codes</property> - </widget> + </object> <packing> <property name="position">5</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="device_tab"> + <object class="GtkVBox" id="device_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox3"> + <object class="GtkVBox" id="vbox4"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox2"> + <object class="GtkHBox" id="hbox15"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image6"> + <object class="GtkImage" id="image6"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="icon_name">media-flash</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label22"> + <object class="GtkLabel" id="label22"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Devices</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator5"> + <object class="GtkHSeparator" id="hseparator6"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1675,24 +1984,28 @@ </packing> </child> <child> - <widget class="GtkVBox" id="vbox5"> + <object class="GtkVBox" id="vbox5"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label41"> + <object class="GtkLabel" id="label41"> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="xpad">12</property> <property name="label" translatable="yes"><b>Devices</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label18"> + <object class="GtkLabel" id="label18"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="xpad">12</property> <property name="label" translatable="yes">Devices are from where to download photos and videos, such as cameras, memory cards or Portable Storage Devices. @@ -1702,39 +2015,46 @@ You can download photos from multiple devices simultaneously, or you can specify <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> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox14"> + <object class="GtkHBox" id="hbox16"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="label26"> + <object class="GtkLabel" id="label26"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xpad">3</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="devices_table"> + <object class="GtkTable" id="devices_table"> <property name="visible">True</property> + <property name="can_focus">False</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"> + <object 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="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_autodetect_psd_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_autodetect_psd_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -1743,27 +2063,29 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkCheckButton" id="autodetect_device_checkbutton"> + <object class="GtkCheckButton" id="autodetect_device_checkbutton"> <property name="label" translatable="yes">Automatically detect 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="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_autodetect_device_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_autodetect_device_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">2</property> </packing> </child> <child> - <widget class="GtkLabel" id="autodetect_image_devices_label"> + <object class="GtkLabel" id="autodetect_image_devices_label"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -1777,42 +2099,50 @@ You can download photos from multiple devices simultaneously, or you can specify <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label28"> + <object class="GtkLabel" id="label28"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox15"> + <object class="GtkHBox" id="hbox17"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkTable" id="devices2_table"> + <object class="GtkTable" id="devices2_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">2</property> <property name="n_columns">2</property> <child> - <widget class="GtkLabel" id="device_location_label"> + <object class="GtkLabel" id="device_location_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="xpad">12</property> <property name="label" translatable="yes">Location:</property> - </widget> + </object> <packing> <property name="top_attach">1</property> <property name="bottom_attach">2</property> @@ -1821,15 +2151,16 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="device_location_explanation_label"> + <object class="GtkLabel" id="device_location_explanation_label"> <property name="visible">True</property> + <property name="can_focus">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="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 and videos.</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="right_attach">2</property> </packing> @@ -1837,8 +2168,10 @@ You can download photos from multiple devices simultaneously, or you can specify <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> @@ -1846,89 +2179,104 @@ You can download photos from multiple devices simultaneously, or you can specify <placeholder/> </child> <child> - <widget class="GtkLabel" id="label30"> + <object class="GtkLabel" id="label30"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">3</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">6</property> </packing> </child> - <child> - <widget class="GtkLabel" id="device_label"> + <child type="tab"> + <object class="GtkLabel" id="device_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Devices</property> - </widget> + </object> <packing> <property name="position">6</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="backup_tab"> + <object class="GtkVBox" id="backup_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkVBox" id="vbox2"> + <object class="GtkVBox" id="vbox8"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox7"> + <object class="GtkHBox" id="hbox19"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image8"> + <object class="GtkImage" id="image8"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="icon_name">drive-removable-media</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label27"> + <object class="GtkLabel" id="label27"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Backup</span> </property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator6"> + <object class="GtkHSeparator" id="hseparator7"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -1936,47 +2284,55 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkVBox" id="vbox9"> + <object class="GtkVBox" id="vbox9"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="label43"> + <object class="GtkLabel" id="label43"> + <property name="can_focus">False</property> <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> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox20"> + <object class="GtkHBox" id="hbox20"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label38"> + <object class="GtkLabel" id="label38"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="backup_table"> + <object class="GtkTable" id="backup_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">9</property> <property name="n_columns">4</property> <child> - <widget class="GtkLabel" id="backup_location_explanation_label"> + <object class="GtkLabel" id="backup_location_explanation_label"> <property name="visible">True</property> + <property name="can_focus">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="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> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">4</property> @@ -1985,15 +2341,16 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkCheckButton" id="auto_detect_backup_checkbutton"> + <object 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="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_auto_detect_backup_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_auto_detect_backup_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">4</property> @@ -2003,28 +2360,30 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="label11"> + <object class="GtkLabel" id="label11"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="ypad">12</property> <property name="label" translatable="yes">You can have your photos and videos backed up to multiple locations as they are downloaded, e.g. external hard drives.</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="right_attach">4</property> <property name="y_options"></property> </packing> </child> <child> - <widget class="GtkCheckButton" id="backup_checkbutton"> + <object class="GtkCheckButton" id="backup_checkbutton"> <property name="label" translatable="yes">Backup photos and videos when downloading</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_backup_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_backup_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">4</property> <property name="top_attach">1</property> @@ -2033,8 +2392,9 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="backup_identifier_explanation_label"> + <object class="GtkLabel" id="backup_identifier_explanation_label"> <property name="visible">True</property> + <property name="can_focus">False</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. @@ -2042,7 +2402,7 @@ You can download photos from multiple devices simultaneously, or you can specify <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 one of these names.</i></property> <property name="use_markup">True</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">4</property> @@ -2051,11 +2411,12 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="backup_location_label"> + <object class="GtkLabel" id="backup_location_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Backup location:</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">3</property> @@ -2066,11 +2427,12 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="backup_identifier_label"> + <object class="GtkLabel" id="backup_identifier_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Photo backup folder name:</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -2082,14 +2444,15 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="backup_example_label"> + <object class="GtkLabel" id="backup_example_label"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -2099,14 +2462,15 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="example_backup_path_label"> + <object class="GtkLabel" id="example_backup_path_label"> <property name="visible">True</property> + <property name="can_focus">False</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> + </object> <packing> <property name="left_attach">3</property> <property name="right_attach">4</property> @@ -2115,12 +2479,17 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkEntry" id="backup_identifier_entry"> + <object 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> + <property name="invisible_char">•</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> + <signal name="changed" handler="on_backup_identifier_entry_changed" swapped="no"/> + </object> <packing> <property name="left_attach">3</property> <property name="right_attach">4</property> @@ -2131,11 +2500,12 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="video_backup_identifier_label"> + <object class="GtkLabel" id="video_backup_identifier_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes">Video backup folder name:</property> - </widget> + </object> <packing> <property name="left_attach">2</property> <property name="right_attach">3</property> @@ -2147,13 +2517,17 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkEntry" id="video_backup_identifier_entry"> + <object class="GtkEntry" id="video_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> - <property name="invisible_char">●</property> - <signal name="changed" handler="on_video_backup_identifier_entry_changed"/> - </widget> + <property name="invisible_char">•</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> + <signal name="changed" handler="on_video_backup_identifier_entry_changed" swapped="no"/> + </object> <packing> <property name="left_attach">3</property> <property name="right_attach">4</property> @@ -2199,94 +2573,112 @@ You can download photos from multiple devices simultaneously, or you can specify <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label39"> + <object class="GtkLabel" id="label39"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">7</property> </packing> </child> - <child> - <widget class="GtkLabel" id="backup_label"> + <child type="tab"> + <object class="GtkLabel" id="backup_label"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes">Backup</property> - </widget> + </object> <packing> <property name="position">7</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="automation_tab"> + <object class="GtkVBox" id="automation_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkVBox" id="vbox4"> + <object class="GtkVBox" id="vbox11"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox10"> + <object class="GtkHBox" id="hbox21"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image4"> + <object class="GtkImage" id="image4"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">gtk-execute</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label31"> + <object 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="can_focus">False</property> + <property name="label" translatable="yes"><span weight="bold" size="x-large">Miscellaneous</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator7"> + <object class="GtkHSeparator" id="hseparator9"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -2294,46 +2686,56 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkVBox" id="vbox11"> + <object class="GtkVBox" id="vbox13"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkLabel" id="label45"> + <object class="GtkLabel" id="label45"> + <property name="visible">True</property> + <property name="can_focus">False</property> <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> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHBox" id="hbox17"> + <object class="GtkHBox" id="hbox24"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkLabel" id="label34"/> + <object class="GtkLabel" id="label34"> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="automation_table"> + <object class="GtkTable" id="automation_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">7</property> <property name="n_columns">3</property> <child> - <widget class="GtkCheckButton" id="auto_unmount_checkbutton"> + <object class="GtkCheckButton" id="auto_unmount_checkbutton"> <property name="label" translatable="yes">Unmount ("eject") 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="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_auto_unmount_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_auto_unmount_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">3</property> <property name="top_attach">2</property> @@ -2341,29 +2743,31 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkCheckButton" id="auto_startup_checkbutton"> + <object 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="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_auto_startup_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_auto_startup_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">3</property> </packing> </child> <child> - <widget class="GtkCheckButton" id="auto_insertion_checkbutton"> + <object class="GtkCheckButton" id="auto_insertion_checkbutton"> <property name="label" translatable="yes">Start downloading upon 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="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_auto_insertion_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_auto_insertion_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">3</property> <property name="top_attach">1</property> @@ -2371,14 +2775,15 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkCheckButton" id="auto_exit_checkbutton"> - <property name="label" translatable="yes">Exit program if download completes without any warnings or errors</property> + <object class="GtkCheckButton" id="auto_exit_checkbutton"> + <property name="label" translatable="yes">Exit program when download completes</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_auto_exit_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_auto_exit_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">3</property> <property name="top_attach">3</property> @@ -2386,16 +2791,34 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkCheckButton" id="auto_delete_checkbutton"> + <object class="GtkCheckButton" id="auto_delete_checkbutton"> <property name="label" translatable="yes">Delete photos and videos from device upon download completion</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_auto_delete_checkbutton_toggled"/> - </widget> + <signal name="toggled" handler="on_auto_delete_checkbutton_toggled" swapped="no"/> + </object> <packing> <property name="right_attach">3</property> + <property name="top_attach">5</property> + <property name="bottom_attach">6</property> + </packing> + </child> + <child> + <object class="GtkCheckButton" id="auto_exit_force_checkbutton"> + <property name="label" translatable="yes">Exit program even if download had warnings or errors</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_auto_exit_force_checkbutton_toggled" swapped="no"/> + </object> + <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> </packing> @@ -2415,101 +2838,197 @@ You can download photos from multiple devices simultaneously, or you can specify <child> <placeholder/> </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">24</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label35"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">12</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xalign">0</property> + <property name="xpad">12</property> + <property name="label" translatable="yes">Performance</property> + <attributes> + <attribute name="weight" value="bold"/> + </attributes> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox25"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkLabel" id="label19"> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkTable" id="table1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="n_columns">3</property> + <child> + <placeholder/> + </child> <child> <placeholder/> </child> - </widget> + <child> + <object class="GtkCheckButton" id="generate_thumbnails_checkbutton"> + <property name="label" translatable="yes">Generate thumbnails (slower)</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> + <property name="draw_indicator">True</property> + <signal name="toggled" handler="on_generate_thumbnails_checkbutton_toggled" swapped="no"/> + </object> + </child> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">24</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label35"> + <object class="GtkLabel" id="label29"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="padding">12</property> - <property name="position">1</property> + <property name="position">3</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">8</property> </packing> </child> - <child> - <widget class="GtkLabel" id="automation_label"> + <child type="tab"> + <object class="GtkLabel" id="miscillaneous_label"> <property name="visible">True</property> + <property name="can_focus">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="label" translatable="yes">Automation</property> - </widget> + <property name="label" translatable="yes">Miscillaneous</property> + </object> <packing> <property name="position">8</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> <child> - <widget class="GtkVBox" id="error_tab"> + <object class="GtkVBox" id="error_tab"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkVBox" id="vbox8"> + <object class="GtkVBox" id="vbox16"> <property name="visible">True</property> + <property name="can_focus">False</property> <child> - <widget class="GtkHBox" id="hbox13"> + <object class="GtkHBox" id="hbox26"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">6</property> <child> - <widget class="GtkImage" id="image9"> + <object class="GtkImage" id="image9"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="stock">gtk-dialog-error</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkLabel" id="label40"> + <object class="GtkLabel" id="label40"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="label" translatable="yes"><span weight="bold" size="x-large">Error Handling</span></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkHSeparator" id="hseparator9"> + <object class="GtkHSeparator" id="hseparator10"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> <property name="fill">False</property> @@ -2517,29 +3036,34 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkHBox" id="hbox19"> + <object class="GtkHBox" id="hbox27"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="spacing">12</property> <child> - <widget class="GtkLabel" id="label36"> + <object class="GtkLabel" id="label36"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">0</property> </packing> </child> <child> - <widget class="GtkTable" id="error_table"> + <object class="GtkTable" id="error_table"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="n_rows">14</property> <property name="n_columns">2</property> <child> - <widget class="GtkLabel" id="label1"> + <object class="GtkLabel" id="label13"> <property name="visible">True</property> + <property name="can_focus">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="label" translatable="yes"> </property> - </widget> + </object> <packing> <property name="top_attach">2</property> <property name="bottom_attach">3</property> @@ -2548,29 +3072,30 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="label12"> + <object class="GtkLabel" id="label37"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="label" translatable="yes"><b>Photo and Video Name Conflicts</b></property> <property name="use_markup">True</property> - </widget> + </object> <packing> <property name="right_attach">2</property> <property name="y_options">GTK_FILL</property> </packing> </child> <child> - <widget class="GtkRadioButton" id="add_identifier_radiobutton"> + <object 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_action_appearance">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> + <signal name="toggled" handler="on_add_identifier_radiobutton_toggled" swapped="no"/> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -2580,15 +3105,16 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkRadioButton" id="skip_download_radiobutton"> + <object 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_action_appearance">False</property> <property name="use_underline">True</property> - <property name="active">True</property> <property name="draw_indicator">True</property> - </widget> + <property name="group">add_identifier_radiobutton</property> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -2598,13 +3124,14 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="label13"> + <object class="GtkLabel" id="label58"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="ypad">12</property> <property name="label" translatable="yes">When a photo or video of the same name has already been downloaded, choose whether to skip downloading the file, or to add a unique indentifier.</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -2614,13 +3141,14 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkLabel" id="label6"> + <object class="GtkLabel" id="label64"> <property name="visible">True</property> + <property name="can_focus">False</property> <property name="xalign">0</property> <property name="ypad">12</property> <property name="label" translatable="yes">When backing up, choose whether to overwrite a file on the backup device that has the same name, or skip backing it up.</property> <property name="wrap">True</property> - </widget> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -2630,16 +3158,16 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkRadioButton" id="backup_duplicate_overwrite_radiobutton"> + <object 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="use_action_appearance">False</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> + <signal name="toggled" handler="on_backup_duplicate_overwrite_radiobutton_toggled" swapped="no"/> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -2648,15 +3176,16 @@ You can download photos from multiple devices simultaneously, or you can specify </packing> </child> <child> - <widget class="GtkRadioButton" id="backup_duplicate_skip_radiobutton"> + <object 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="use_action_appearance">False</property> <property name="active">True</property> <property name="draw_indicator">True</property> - <signal name="toggled" handler="on_backup_duplicate_skip_radiobutton_toggled"/> - </widget> + <signal name="toggled" handler="on_backup_duplicate_skip_radiobutton_toggled" swapped="no"/> + </object> <packing> <property name="left_attach">1</property> <property name="right_attach">2</property> @@ -2721,52 +3250,61 @@ You can download photos from multiple devices simultaneously, or you can specify <child> <placeholder/> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="position">1</property> </packing> </child> <child> - <widget class="GtkLabel" id="label37"> + <object class="GtkLabel" id="label65"> <property name="visible">True</property> - </widget> + <property name="can_focus">False</property> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="position">2</property> </packing> </child> - </widget> + </object> <packing> <property name="expand">False</property> + <property name="fill">True</property> <property name="padding">12</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> <property name="position">9</property> </packing> </child> - <child> - <widget class="GtkLabel" id="error_label"> + <child type="tab"> + <object class="GtkLabel" id="error_label"> <property name="visible">True</property> + <property name="can_focus">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="label" translatable="yes">Error Handling</property> - </widget> + </object> <packing> <property name="position">9</property> <property name="tab_fill">False</property> - <property name="type">tab</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">6</property> <property name="position">1</property> </packing> </child> - </widget> + </object> <packing> + <property name="expand">True</property> + <property name="fill">True</property> <property name="padding">5</property> <property name="position">1</property> </packing> @@ -2774,786 +3312,11 @@ You can download photos from multiple devices simultaneously, or you can specify <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.svg</property> - <property name="type_hint">normal</property> - <property name="program_name">Rapid Photo Downloader</property> - <property name="copyright" translatable="yes">Copyright Damon Lynch 2007-11</property> - <property name="comments" translatable="yes">Import your photos and videos 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">Anton Alyab'ev <subeditor@dolgopa.org> -Lőrincz András <level.andrasnak@gmail.com> -Michel Ange <michelange@wanadoo.fr> -Alain J. Baudrez <a.baudrez@gmail.com> -Bert <crinbert@yahoo.com> -Martin Dahl Moe -Martin Egger <martin.egger@gmx.net> -Miroslav Matejaš <silverspace@ubuntu-hr.org> -Nicolás M. Zahlut <nzahlut@live.com> -Erik M -Jose Luis Navarro <jlnavarro111@gmail.com> -Tomas Novak <kuvaly@seznam.cz> -Abel O'Rian <abel.orian@gmail.com> -Balazs Oveges <ovegesb@freemail.hu> -Daniel Paessler <daniel@paessler.org> -Miloš Popović <gpopac@gmail.com> -Michal Predotka <mpredotka@googlemail.com> -Ye Qing <allen19920930@gmail.com> -Luca Reverberi <thereve@gmail.com> -Mikko Ruohola <polarfox@polarfox.net> -Sergiy Gavrylov <sergiovana@bigmir.net> -Sergei Sedov <sedov@webmail.perm.ru> -Marco Solari <marcosolari@gmail.com> -Toni Lähdekorpi <toni@lygon.net> -Ulf Urdén <ulf.urden@purplescout.com> -Julien Valroff <julien@kirya.net> -Aron Xu <happyaron.xu@gmail.com> -梁其学 <yalongbay@gmail.com></property> - <property name="logo">rapid-photo-downloader.svg</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="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="default_width">650</property> - <property name="icon">rapid-photo-downloader.svg</property> - <signal name="destroy" handler="on_rapidapp_destroy"/> - <signal name="window_state_event" handler="on_rapidapp_window_state_event"/> - <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">_File</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_refresh"> - <property name="label">gtk-refresh</property> - <property name="visible">True</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - <signal name="activate" handler="on_menu_refresh_activate"/> - <accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </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"/> - <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </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="select_menuitem"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Select</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="select_menu"> - <child> - <widget class="GtkMenuItem" id="menu_select_all"> - <property name="visible">True</property> - <property name="label" translatable="yes">Select _All</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_menu_select_all_activate"/> - <accelerator key="a" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menu_select_all_photos"> - <property name="visible">True</property> - <property name="label" translatable="yes">Select All Pho_tos</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_menu_select_all_photos_activate"/> - <accelerator key="t" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menu_select_all_videos"> - <property name="visible">True</property> - <property name="label" translatable="yes">Select All Vi_deos</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_menu_select_all_videos_activate"/> - <accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menu_select_none"> - <property name="visible">True</property> - <property name="label" translatable="yes">Se_lect None</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_menu_select_none_activate"/> - <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="menu_select_sep"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menu_select_all_without_job_code"> - <property name="visible">True</property> - <property name="label" translatable="yes">Select All Without _Job Code</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_menu_select_all_without_job_code_activate"/> - <accelerator key="j" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menu_select_all_with_job_code"> - <property name="visible">True</property> - <property name="label" translatable="yes">Select All Wit_h Job Code</property> - <property name="use_underline">True</property> - <signal name="activate" handler="on_menu_select_all_with_job_code_activate"/> - <accelerator key="h" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </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_selection"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Preview</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_display_selection_toggled"/> - </widget> - </child> - <child> - <widget class="GtkMenuItem" id="menu_preview_columns"> - <property name="visible">True</property> - <property name="label" translatable="yes">P_review Columns</property> - <property name="use_underline">True</property> - <child> - <widget class="GtkMenu" id="menu1"> - <property name="visible">True</property> - <child> - <widget class="GtkCheckMenuItem" id="menu_type_column"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Type</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_type_column_toggled"/> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="menu_size_column"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Size</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_size_column_toggled"/> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="menu_device_column"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Device</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_device_column_toggled"/> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="menu_filename_column"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Filename</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_filename_column_toggled"/> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="menu_path_column"> - <property name="visible">True</property> - <property name="label" translatable="yes">_Path</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_path_column_toggled"/> - </widget> - </child> - </widget> - </child> - </widget> - </child> - <child> - <widget class="GtkCheckMenuItem" id="menu_preview_folders"> - <property name="visible">True</property> - <property name="label" translatable="yes">Preview _Folders</property> - <property name="use_underline">True</property> - <signal name="toggled" handler="on_menu_preview_folders_toggled"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="seperator40"> - <property name="visible">True</property> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="menu_zoom_in"> - <property name="label">gtk-zoom-in</property> - <property name="visible">True</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - <signal name="activate" handler="on_menu_zoom_in_activate"/> - <accelerator key="plus" signal="activate" modifiers="GDK_CONTROL_MASK"/> - <accelerator key="equal" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkImageMenuItem" id="menu_zoom_out"> - <property name="label">gtk-zoom-out</property> - <property name="visible">True</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - <signal name="activate" handler="on_menu_zoom_out_activate"/> - <accelerator key="minus" signal="activate" modifiers="GDK_CONTROL_MASK"/> - </widget> - </child> - <child> - <widget class="GtkSeparatorMenuItem" id="seperator20"> - <property name="visible">True</property> - </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="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> - <child> - <widget class="GtkSeparatorMenuItem" id="separator5"> - <property name="visible">True</property> - </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="GtkImageMenuItem" id="menu_get_help_online"> - <property name="label" translatable="yes">_Get Help Online...</property> - <property name="visible">True</property> - <property name="use_underline">True</property> - <property name="use_stock">False</property> - <signal name="activate" handler="on_menu_get_help_online_activate"/> - <accelerator key="F1" signal="activate"/> - <child internal-child="image"> - <widget class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="icon_name">help</property> - </widget> - </child> - </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="GtkVPaned" id="main_vpaned"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <child> - <widget class="GtkVBox" id="device_vbox"> - <property name="visible">True</property> - <child> - <widget class="GtkHBox" id="media_collection_area_hbox"> - <property name="visible">True</property> - <property name="spacing">6</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> - <property name="resize_mode">queue</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> - </widget> - <packing> - <property name="resize">False</property> - <property name="shrink">False</property> - </packing> - </child> - <child> - <widget class="GtkTable" id="selection_table"> - <property name="visible">True</property> - <property name="n_rows">2</property> - <property name="row_spacing">3</property> - <child> - <widget class="GtkHBox" id="selection_hbox"> - <property name="visible">True</property> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="top_attach">1</property> - <property name="bottom_attach">2</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </widget> - <packing> - <property name="resize">True</property> - <property name="shrink">False</property> - </packing> - </child> - </widget> - <packing> - <property name="position">0</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">1</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="GtkHBox" id="hbox2"> - <property name="visible">True</property> - <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">0</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="GtkVSeparator" id="warning_vseparator"> - <property name="visible">True</property> - </widget> - <packing> - <property name="expand">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> - <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">2</property> - </packing> - </child> - </widget> - </child> - </widget> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </widget> - <packing> - <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="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">5</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.svg</property> - <property name="type_hint">dialog</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> + </object> </child> - </widget> -</glade-interface> + <action-widgets> + <action-widget response="-11">help_button1</action-widget> + <action-widget response="-7">close_button</action-widget> + </action-widgets> + </object> +</interface> diff --git a/rapid/glade3/rapid-photo-downloader-download-pending.png b/rapid/glade3/rapid-photo-downloader-download-pending.png Binary files differnew file mode 100644 index 0000000..e12cc69 --- /dev/null +++ b/rapid/glade3/rapid-photo-downloader-download-pending.png diff --git a/rapid/glade3/rapid-photo-downloader-download-pending.svg b/rapid/glade3/rapid-photo-downloader-download-pending.svg deleted file mode 100644 index d6127b7..0000000 --- a/rapid/glade3/rapid-photo-downloader-download-pending.svg +++ /dev/null @@ -1,187 +0,0 @@ -<?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://creativecommons.org/ns#" - 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" - version="1.0" - width="16" - height="16" - id="svg4136" - inkscape:version="0.47 r22583" - sodipodi:docname="rapid-photo-downloader-image-loading.svg"> - <metadata - id="metadata33"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <sodipodi:namedview - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1" - objecttolerance="10" - gridtolerance="10" - guidetolerance="10" - inkscape:pageopacity="0" - inkscape:pageshadow="2" - inkscape:window-width="1920" - inkscape:window-height="1089" - id="namedview31" - showgrid="false" - inkscape:zoom="9.8333333" - inkscape:cx="12" - inkscape:cy="12" - inkscape:window-x="0" - inkscape:window-y="24" - inkscape:window-maximized="1" - inkscape:current-layer="svg4136" /> - <defs - id="defs4138"> - <inkscape:perspective - sodipodi:type="inkscape:persp3d" - inkscape:vp_x="0 : 12 : 1" - inkscape:vp_y="0 : 1000 : 0" - inkscape:vp_z="24 : 12 : 1" - inkscape:persp3d-origin="12 : 8 : 1" - id="perspective35" /> - <linearGradient - id="linearGradient8838"> - <stop - id="stop8840" - style="stop-color:black;stop-opacity:1" - offset="0" /> - <stop - id="stop8842" - style="stop-color:black;stop-opacity:0" - offset="1" /> - </linearGradient> - <radialGradient - cx="62.625" - cy="4.625" - r="10.625" - fx="62.625" - fy="4.625" - id="radialGradient5323" - xlink:href="#linearGradient8838" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.341176,0,3.047059)" /> - <linearGradient - id="linearGradient5354"> - <stop - id="stop5356" - style="stop-color:#3f3f3f;stop-opacity:1" - offset="0" /> - <stop - id="stop5358" - style="stop-color:black;stop-opacity:1" - offset="1" /> - </linearGradient> - <linearGradient - x1="19.176617" - y1="13.479795" - x2="19.176617" - y2="45.358662" - id="linearGradient5130" - xlink:href="#linearGradient5354" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.4916775,0,0,0.4916774,0.6986745,-0.3018277)" /> - <linearGradient - id="linearGradient37935"> - <stop - id="stop37937" - style="stop-color:#929292;stop-opacity:1" - offset="0" /> - <stop - id="stop37939" - style="stop-color:#4a4a4a;stop-opacity:1" - offset="1" /> - </linearGradient> - <linearGradient - x1="28.771276" - y1="12.91806" - x2="28.771276" - y2="45.347591" - id="linearGradient5128" - xlink:href="#linearGradient37935" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.4916775,0,0,0.4916774,0.6986745,-0.3018277)" /> - <linearGradient - id="linearGradient2145"> - <stop - id="stop2147" - style="stop-color:#fffffd;stop-opacity:1" - offset="0" /> - <stop - id="stop2149" - style="stop-color:#cbcbc9;stop-opacity:1" - offset="1" /> - </linearGradient> - <radialGradient - cx="11.901996" - cy="10.045444" - r="29.292715" - fx="11.901996" - fy="10.045444" - id="radialGradient5350" - xlink:href="#linearGradient2145" - gradientUnits="userSpaceOnUse" /> - </defs> - <g - id="layer1" - transform="matrix(0.652174,0,0,0.65491337,-0.15217376,0.2820791)"> - <path - d="m 73.25,4.625 a 10.625,3.625 0 1 1 -21.25,0 10.625,3.625 0 1 1 21.25,0 z" - transform="matrix(1.0823528,0,0,1.2906765,-55.282346,13.351919)" - id="path2774" - style="opacity:0.56043958;fill:url(#radialGradient5323);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.99999988;marker:none;visibility:visible;display:inline;overflow:visible" /> - <path - d="m 12.492145,1.4999735 c -5.5190685,0 -9.9921705,4.473101 -9.9921705,9.9921715 0,5.519069 4.473102,10.007882 9.9921705,10.007881 5.519068,0 10.007887,-4.488812 10.007882,-10.007881 0,-5.5190705 -4.488814,-9.9921715 -10.007882,-9.9921715 z" - id="path2555" - style="fill:url(#linearGradient5128);fill-opacity:1;stroke:url(#linearGradient5130);stroke-width:0.99994898;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" /> - <path - d="m 31.160714,16.910715 a 14.910714,14.910714 0 1 1 -29.8214281,0 14.910714,14.910714 0 1 1 29.8214281,0 z" - transform="matrix(0.5700599,0,0,0.5700599,3.2365269,1.8598792)" - id="path35549" - style="fill:url(#radialGradient5350);fill-opacity:1;fill-rule:evenodd;stroke:none" /> - <path - d="m 12.5,6.4999999 c 0,-1.3926725 0,-1.5690116 0,-1.5690116" - id="path2308" - style="fill:#1f1f1f;fill-opacity:1;fill-rule:evenodd;stroke:#727272;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - d="M 12.194529,11.713855 17.596253,6.3122524" - id="path2312" - style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - d="M 13.071561,11.753718 9.4637681,8.1460064" - id="path2314" - style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - d="M 12.314125,11.434805 18.465311,9.7866365" - id="path2316" - style="fill:#ff0000;fill-rule:evenodd;stroke:#ff0000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - d="m 12.5,18.284507 c 0,-1.392673 0,-1.569012 0,-1.569012" - id="path5368" - style="fill:#121212;fill-opacity:1;fill-rule:evenodd;stroke:#121212;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - d="m 17.5,11.5 c 1.392673,0 1.569013,0 1.569013,0" - id="path5370" - style="fill:#1f1f1f;fill-opacity:1;fill-rule:evenodd;stroke:#1f1f1f;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - <path - d="m 5.7331351,11.5 c 1.3613563,0 1.5337301,0 1.5337301,0" - id="path5372" - style="fill:#1f1f1f;fill-opacity:1;fill-rule:evenodd;stroke:#5f5f5f;stroke-width:1.00000012;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> - </g> -</svg> diff --git a/rapid/glade3/rapid.ui b/rapid/glade3/rapid.ui new file mode 100644 index 0000000..bd9638e --- /dev/null +++ b/rapid/glade3/rapid.ui @@ -0,0 +1,993 @@ +<?xml version="1.0" encoding="UTF-8"?> +<interface> + <requires lib="gtk+" version="2.20"/> + <!-- interface-naming-policy project-wide --> + <object class="GtkAction" id="about_action"> + <property name="label" translatable="yes">About...</property> + <property name="stock_id">gtk-about</property> + <signal name="activate" handler="on_about_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="check_all_action"> + <property name="label" translatable="yes">Check All</property> + <signal name="activate" handler="on_check_all_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="check_all_photos_action"> + <property name="label" translatable="yes">Check All Photos</property> + <signal name="activate" handler="on_check_all_photos_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="check_all_videos_action"> + <property name="label" translatable="yes">Check All Videos</property> + <signal name="activate" handler="on_check_all_videos_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="donate_action"> + <property name="label" translatable="yes">Make a Donation...</property> + <signal name="activate" handler="on_donate_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="download_action"> + <property name="label">Download</property> + <property name="icon_name">system-run</property> + <property name="sensitive">False</property> + <signal name="activate" handler="on_download_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="get_help_action"> + <property name="label" translatable="yes">Get Help Online...</property> + <property name="stock_id">gtk-help</property> + <signal name="activate" handler="on_get_help_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="help_action"> + <property name="label">Help</property> + <signal name="activate" handler="on_help_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="next_image_action"> + <property name="label" translatable="yes">Next File</property> + <property name="tooltip">Next file</property> + <property name="stock_id">gtk-go-forward</property> + <property name="always_show_image">True</property> + <signal name="activate" handler="on_next_image_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="preferences_action"> + <property name="label">Preferences</property> + <signal name="activate" handler="on_preferences_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="prev_image_action"> + <property name="label" translatable="yes">Previous File</property> + <property name="tooltip">Previous file</property> + <property name="stock_id">gtk-go-back</property> + <property name="always_show_image">True</property> + <signal name="activate" handler="on_prev_image_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="quit_action"> + <property name="label" translatable="yes">Quit</property> + <property name="stock_id">gtk-quit</property> + <signal name="activate" handler="on_quit_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="refresh_action"> + <property name="label" translatable="yes">Refresh</property> + <property name="stock_id">gtk-refresh</property> + <signal name="activate" handler="on_refresh_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="report_problem_action"> + <property name="label" translatable="yes">Report a Problem...</property> + <property name="stock_id">gtk-dialog-warning</property> + <signal name="activate" handler="on_report_problem_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="show_image_action"> + <property name="tooltip">Show image</property> + <signal name="activate" handler="on_show_image_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="show_thumbnails_action"> + <property name="tooltip">Show thumbnails</property> + <signal name="activate" handler="on_show_thumbnails_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="translate_action"> + <property name="label" translatable="yes">Translate this Application...</property> + <signal name="activate" handler="on_translate_action_activate" swapped="no"/> + </object> + <object class="GtkAction" id="uncheck_all_action"> + <property name="label" translatable="yes">Uncheck All</property> + <signal name="activate" handler="on_uncheck_all_action_activate" swapped="no"/> + </object> + <object class="GtkWindow" id="rapidapp"> + <property name="can_focus">False</property> + <property name="title" translatable="yes">Rapid Photo Downloader</property> + <property name="icon">rapid-photo-downloader.svg</property> + <signal name="destroy" handler="on_rapidapp_destroy" swapped="no"/> + <signal name="window-state-event" handler="on_rapidapp_window_state_event" swapped="no"/> + <child> + <object class="GtkVBox" id="rapidapp_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkMenuBar" id="menubar3"> + <property name="visible">True</property> + <property name="can_focus">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="ubuntu_local">True</property> + <child> + <object class="GtkMenuItem" id="menuitem7"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="menuitem7_menu"> + <property name="can_focus">False</property> + <property name="ubuntu_local">True</property> + <child> + <object class="GtkImageMenuItem" id="menu_download_pause"> + <property name="label" translatable="yes">Download / Pause</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">download_action</property> + <property name="use_stock">False</property> + <accelerator key="Return" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="menu_refresh"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">refresh_action</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="menu_preferences"> + <property name="label">gtk-preferences</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">preferences_action</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="menu_quit"> + <property name="label">gtk-quit</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">quit_action</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkMenuItem" id="select_menuitem"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Select</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="select_menu"> + <property name="can_focus">False</property> + <property name="ubuntu_local">True</property> + <child> + <object class="GtkMenuItem" id="menu_check_all"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">check_all_action</property> + <accelerator key="a" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_check_all_photos"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">check_all_photos_action</property> + <accelerator key="t" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_check_all_videos"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">check_all_videos_action</property> + <accelerator key="d" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_uncheck_all"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">uncheck_all_action</property> + <accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="menu_select_sep"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_select_all_without_job_code"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">Select All Without _Job Code</property> + <property name="use_underline">True</property> + <accelerator key="j" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_select_all_with_job_code"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">Select All Wit_h Job Code</property> + <property name="use_underline">True</property> + <accelerator key="h" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menuitem10"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_View</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="menuitem10_menu"> + <property name="can_focus">False</property> + <property name="ubuntu_local">True</property> + <child> + <object class="GtkImageMenuItem" id="menu_zoom_in"> + <property name="label">gtk-zoom-in</property> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <accelerator key="plus" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <accelerator key="equal" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="menu_zoom_out"> + <property name="label">gtk-zoom-out</property> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <accelerator key="minus" signal="activate" modifiers="GDK_CONTROL_MASK"/> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="seperator20"> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + </object> + </child> + <child> + <object class="GtkCheckMenuItem" id="menu_log_window"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Error Log</property> + <property name="use_underline">True</property> + <signal name="toggled" handler="on_menu_log_window_toggled" swapped="no"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_clear"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Clear Completed Downloads</property> + <property name="use_underline">True</property> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="separator5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> + <child> + <object class="GtkMenuItem" id="previous_image_menuitem"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">prev_image_action</property> + <accelerator key="bracketleft" signal="activate"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="next_file_menuitem"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">next_image_action</property> + <accelerator key="bracketright" signal="activate"/> + </object> + </child> + </object> + </child> + </object> + </child> + <child> + <object class="GtkMenuItem" id="help_menuitem"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + <child type="submenu"> + <object class="GtkMenu" id="help_menu"> + <property name="can_focus">False</property> + <property name="ubuntu_local">True</property> + <child> + <object class="GtkImageMenuItem" id="menu_get_help_online"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">get_help_action</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + <accelerator key="F1" signal="activate"/> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_report_problem"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">report_problem_action</property> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_donate"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">donate_action</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Make a Donation...</property> + <property name="use_underline">True</property> + </object> + </child> + <child> + <object class="GtkMenuItem" id="menu_translate"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">translate_action</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">_Translate this Application...</property> + <property name="use_underline">True</property> + </object> + </child> + <child> + <object class="GtkSeparatorMenuItem" id="separator1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + </child> + <child> + <object class="GtkImageMenuItem" id="menu_about"> + <property name="label">gtk-about</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="related_action">about_action</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="use_stock">True</property> + </object> + </child> + </object> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkVPaned" id="main_vpaned"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="position">1</property> + <property name="position_set">True</property> + <child> + <object class="GtkScrolledWindow" id="device_collection_scrolledwindow"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">never</property> + <property name="vscrollbar_policy">automatic</property> + <child> + <object class="GtkViewport" id="device_collection_viewport"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="resize_mode">queue</property> + <property name="shadow_type">none</property> + <child> + <placeholder/> + </child> + </object> + </child> + </object> + <packing> + <property name="resize">False</property> + <property name="shrink">False</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="thumbnail_pane_vbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkNotebook" id="main_notebook"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="show_tabs">False</property> + <property name="show_border">False</property> + <child> + <object class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkScrolledWindow" id="thumbnails_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> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkHBox" id="thumbnail_control_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <placeholder/> + </child> + <child> + <object class="GtkButton" id="preview_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">show_image_action</property> + <property name="relief">none</property> + <property name="focus_on_click">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="check_all_button"> + <property name="label" translatable="yes">_Check All</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">check_all_action</property> + <property name="relief">none</property> + <property name="use_underline">True</property> + <property name="focus_on_click">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkButton" id="uncheck_all_button"> + <property name="label" translatable="yes">_Uncheck All</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">uncheck_all_action</property> + <property name="relief">none</property> + <property name="use_underline">True</property> + <property name="focus_on_click">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">3</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">4</property> + <property name="position">0</property> + </packing> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> + <child type="tab"> + <object class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label">page 1</property> + </object> + <packing> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkEventBox" id="preview_eventbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="no_show_all">True</property> + <signal name="button-press-event" handler="on_preview_eventbox_button_press_event" swapped="no"/> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="homogeneous">True</property> + <child> + <object class="GtkHBox" id="image_controls_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">6</property> + <child> + <object class="GtkButton" id="next_image_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">next_image_action</property> + <property name="use_action_appearance">False</property> + <property name="relief">none</property> + <property name="focus_on_click">False</property> + <accelerator key="bracketright" signal="activate"/> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="prev_image_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">prev_image_action</property> + <property name="use_action_appearance">False</property> + <property name="relief">none</property> + <property name="focus_on_click">False</property> + <accelerator key="bracketleft" signal="activate"/> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">6</property> + <property name="pack_type">end</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkButton" id="thumbnails_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">show_thumbnails_action</property> + <property name="relief">none</property> + <property name="use_underline">True</property> + <property name="focus_on_click">False</property> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="padding">4</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkCheckButton" id="download_this_checkbutton"> + <property name="label" translatable="yes">_Include in download</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="use_action_appearance">False</property> + <property name="use_underline">True</property> + <property name="draw_indicator">True</property> + <accelerator key="i" signal="activate"/> + <signal name="toggled" handler="on_download_this_checkbutton_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="position">1</property> + </packing> + </child> + <child type="tab"> + <object class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label">page 2</property> + </object> + <packing> + <property name="position">1</property> + <property name="tab_fill">False</property> + </packing> + </child> + <child> + <placeholder/> + </child> + <child type="tab"> + <object class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label">page 3</property> + </object> + <packing> + <property name="position">2</property> + <property name="tab_fill">False</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="resize">True</property> + <property name="shrink">True</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="buttons_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkHButtonBox" id="main_buttonbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="layout_style">edge</property> + <child> + <object class="GtkButton" id="help_button"> + <property name="label">_Help</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="related_action">help_action</property> + <property name="use_underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkButton" id="download_button"> + <property name="label" translatable="yes">_Download</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="receives_default">True</property> + <property name="related_action">download_action</property> + <property name="use_underline">True</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="padding">6</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="padding">6</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="statusbar_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkHBox" id="download_progressbar_hbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkProgressBar" id="download_progressbar"> + <property name="width_request">0</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkStatusbar" id="rapid_statusbar"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">2</property> + <property name="has_resize_grip">False</property> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkVSeparator" id="vseparator1"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">2</property> + </packing> + </child> + <child> + <object class="GtkVBox" id="vbox15"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkHSeparator" id="hseparator3"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkHBox" id="hbox5"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="speed_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label"> </property> + <property name="width_chars">9</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkEventBox" id="error_eventbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <signal name="button-press-event" handler="on_error_eventbox_button_press_event" swapped="no"/> + <child> + <object class="GtkHBox" id="hbox6"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkVSeparator" id="warning_vseparator"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkImage" id="error_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="xpad">3</property> + <property name="stock">gtk-dialog-error</property> + <property name="icon-size">1</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkImage" id="warning_image"> + <property name="visible">True</property> + <property name="can_focus">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="xpad">3</property> + <property name="stock">gtk-dialog-warning</property> + <property name="icon-size">1</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">2</property> + </packing> + </child> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkVSeparator" id="vseparator2"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> + <child> + <object class="GtkStatusbar" id="statusbar1"> + <property name="width_request">15</property> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">2</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="position">5</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">end</property> + <property name="position">3</property> + </packing> + </child> + </object> + </child> + </object> +</interface> diff --git a/rapid/glade3/thumbnails_icon.png b/rapid/glade3/thumbnails_icon.png Binary files differnew file mode 100644 index 0000000..d76d954 --- /dev/null +++ b/rapid/glade3/thumbnails_icon.png diff --git a/rapid/glade3/video.png b/rapid/glade3/video.png Binary files differdeleted file mode 100644 index 2dfc666..0000000 --- a/rapid/glade3/video.png +++ /dev/null diff --git a/rapid/glade3/video.svg b/rapid/glade3/video.svg new file mode 100644 index 0000000..0817d62 --- /dev/null +++ b/rapid/glade3/video.svg @@ -0,0 +1,956 @@ +<?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://creativecommons.org/ns#" + 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" + version="1.0" + width="96" + height="96" + id="svg2408" + inkscape:version="0.48.1 r9760" + sodipodi:docname="video.svg" + inkscape:export-filename="/home/damon/rapid/rapid/glade3/video66.png" + inkscape:export-xdpi="61.880001" + inkscape:export-ydpi="61.880001"> + <sodipodi:namedview + pagecolor="#444444" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="1" + inkscape:pageshadow="2" + inkscape:window-width="950" + inkscape:window-height="950" + id="namedview3275" + showgrid="false" + inkscape:zoom="3.0104167" + inkscape:cx="48" + inkscape:cy="48" + inkscape:window-x="93" + inkscape:window-y="58" + inkscape:window-maximized="0" + inkscape:current-layer="svg2408" /> + <defs + id="defs2410"> + <linearGradient + id="linearGradient4314"> + <stop + id="stop4316" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop4322" + style="stop-color:#ffffff;stop-opacity:0.49803922" + offset="0.30000001" /> + <stop + id="stop4318" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="45.447727" + y1="92.539597" + x2="45.447727" + y2="7.0165396" + id="ButtonShadow" + gradientUnits="userSpaceOnUse" + gradientTransform="scale(1.0058652,0.994169)"> + <stop + id="stop3750" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3752" + style="stop-color:#000000;stop-opacity:0.58823532" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3737"> + <stop + id="stop3739" + style="stop-color:#ffffff;stop-opacity:1" + offset="0" /> + <stop + id="stop3741" + style="stop-color:#ffffff;stop-opacity:0" + offset="1" /> + </linearGradient> + <filter + color-interpolation-filters="sRGB" + id="filter3174"> + <feGaussianBlur + id="feGaussianBlur3176" + stdDeviation="1.71" /> + </filter> + <linearGradient + x1="36.357143" + y1="6" + x2="36.357143" + y2="63.893143" + id="linearGradient3188" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" /> + <filter + x="-0.192" + y="-0.192" + width="1.3839999" + height="1.3839999" + color-interpolation-filters="sRGB" + id="filter3794"> + <feGaussianBlur + id="feGaussianBlur3796" + stdDeviation="5.28" /> + </filter> + <linearGradient + x1="48" + y1="20.220806" + x2="48" + y2="138.66119" + id="linearGradient3613" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="48" + cy="90.171875" + r="42" + fx="48" + fy="90.171875" + id="radialGradient3619" + xlink:href="#linearGradient3737" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.1573129,0,0,0.99590774,-7.5510206,0.19713193)" /> + <clipPath + id="clipPath3613"> + <rect + width="84" + height="84" + rx="6" + ry="6" + x="6" + y="6" + id="rect3615" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </clipPath> + <linearGradient + x1="48" + y1="90" + x2="48" + y2="5.9877172" + id="linearGradient3617" + xlink:href="#linearGradient3187" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3187"> + <stop + id="stop3189" + style="stop-color:#282828;stop-opacity:1" + offset="0" /> + <stop + id="stop3191" + style="stop-color:#5a5a5a;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3386"> + <stop + id="stop3388" + style="stop-color:#eeeeec;stop-opacity:1" + offset="0" /> + <stop + id="stop3390" + style="stop-color:#eeeeec;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + cx="53.419292" + cy="66.597893" + r="47.724609" + fx="53.419292" + fy="66.597893" + id="radialGradient3904" + xlink:href="#linearGradient3386" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0164118,0,0,1.2415079,-19.337623,-31.113008)" /> + <radialGradient + cx="53.419292" + cy="66.597893" + r="47.724609" + fx="53.419292" + fy="66.597893" + id="radialGradient3929" + xlink:href="#linearGradient3386" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0220726,0,0,1.2415079,-19.896446,-47.863009)" /> + <radialGradient + cx="53.419292" + cy="66.597893" + r="47.724609" + fx="53.419292" + fy="66.597893" + id="radialGradient3933" + xlink:href="#linearGradient3386" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4750367,0,0,0.847859,-55.736923,-9.8942437)" /> + <radialGradient + cx="53.419292" + cy="66.597893" + r="47.724609" + fx="53.419292" + fy="66.597893" + id="radialGradient3937" + xlink:href="#linearGradient3386" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4750367,0,0,0.847859,-77.736923,-9.8942437)" /> + <radialGradient + cx="53.419292" + cy="66.597893" + r="47.724609" + fx="53.419292" + fy="66.597893" + id="radialGradient4114" + xlink:href="#linearGradient3386" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0199392,0,0,0.85846172,-19.873341,-11.926904)" /> + <radialGradient + cx="53.419292" + cy="66.597893" + r="47.724609" + fx="53.419292" + fy="66.597893" + id="radialGradient4116" + xlink:href="#linearGradient3386" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0199392,0,0,0.85846172,-19.685841,-9.268213)" /> + <linearGradient + id="linearGradient3299"> + <stop + id="stop3301" + style="stop-color:#dfdfdf;stop-opacity:1" + offset="0" /> + <stop + id="stop3303" + style="stop-color:#434343;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3273"> + <stop + id="stop3275" + style="stop-color:#5d5d5d;stop-opacity:1" + offset="0" /> + <stop + id="stop3277" + style="stop-color:#171717;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3289"> + <stop + id="stop3291" + style="stop-color:#919191;stop-opacity:1" + offset="0" /> + <stop + id="stop3293" + style="stop-color:#232323;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3260" + gradientUnits="userSpaceOnUse"> + <stop + id="stop3262" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3266" + style="stop-color:#000000;stop-opacity:0.3548387" + offset="0.2" /> + <stop + id="stop3268" + style="stop-color:#000000;stop-opacity:0" + offset="0.55254942" /> + <stop + id="stop3264" + style="stop-color:#000000;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="43.476658" + y1="26" + x2="43.476658" + y2="34.001266" + id="linearGradient4262" + xlink:href="#linearGradient3260" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.72413795,0,0,0.75,1.6551725,4.5)" /> + <linearGradient + x1="48" + y1="16" + x2="48" + y2="11.924657" + id="linearGradient4310" + xlink:href="#linearGradient3260" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.25,0,-4.5982122)" /> + <linearGradient + x1="50.464287" + y1="16.035713" + x2="50.464287" + y2="20.329885" + id="linearGradient4320" + xlink:href="#linearGradient4314" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,-0.67856979)" /> + <linearGradient + x1="48" + y1="16" + x2="48" + y2="11.924657" + id="linearGradient4326" + xlink:href="#linearGradient3260" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1,0,0,1.25,0,4.4017878)" /> + <linearGradient + x1="11" + y1="10.441942" + x2="16" + y2="24" + id="linearGradient4371" + xlink:href="#linearGradient3273" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.81330712,0,0,0.81132563,3.9935431,2.0281849)" /> + <linearGradient + x1="13.125" + y1="9.9419422" + x2="19.25" + y2="24.5" + id="linearGradient4373" + xlink:href="#linearGradient3289" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.81330712,0,0,0.81132563,3.9935431,2.0281849)" /> + <radialGradient + cx="11.3125" + cy="14.9375" + r="1.4375" + fx="11.3125" + fy="14.9375" + id="radialGradient4375" + xlink:href="#linearGradient3299" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="11.3125" + cy="14.9375" + r="1.4375" + fx="11.3125" + fy="14.9375" + id="radialGradient4377" + xlink:href="#linearGradient3299" + gradientUnits="userSpaceOnUse" /> + <radialGradient + cx="11.3125" + cy="14.9375" + r="1.4375" + fx="11.3125" + fy="14.9375" + id="radialGradient4379" + xlink:href="#linearGradient3299" + gradientUnits="userSpaceOnUse" /> + <linearGradient + id="linearGradient3277"> + <stop + id="stop3279" + style="stop-color:#3d9119;stop-opacity:1" + offset="0" /> + <stop + id="stop3281" + style="stop-color:#76e62b;stop-opacity:1" + offset="1" /> + </linearGradient> + <linearGradient + id="linearGradient3266"> + <stop + id="stop3269" + style="stop-color:#87ff2b;stop-opacity:1" + offset="0" /> + <stop + id="stop3271" + style="stop-color:#87ff2b;stop-opacity:0" + offset="1" /> + </linearGradient> + <linearGradient + x1="70.782135" + y1="83.017471" + x2="75.404488" + y2="22.02951" + id="linearGradient4520" + xlink:href="#linearGradient3277" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0513134,0,0,1.0513134,-120.2285,31.416155)" /> + <radialGradient + cx="40.846539" + cy="75.263962" + r="14.672466" + fx="40.846539" + fy="75.263962" + id="radialGradient4522" + xlink:href="#linearGradient3266" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9847961,0.02597927,-0.01823822,0.6913564,1.9937062,24.820256)" /> + <radialGradient + cx="40.846539" + cy="75.263962" + r="14.672466" + fx="40.846539" + fy="75.263962" + id="radialGradient4524" + xlink:href="#linearGradient3266" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9847961,0.02597927,-0.01823822,0.6913564,1.9937062,24.820256)" /> + <radialGradient + cx="54.75" + cy="25.072803" + r="13" + fx="54.75" + fy="25.072803" + id="radialGradient4526" + xlink:href="#linearGradient3266" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.543369,0.28142051,-0.32722971,1.7945958,-138.17549,-6.0460513)" /> + <radialGradient + cx="56.496048" + cy="31.701607" + r="13" + fx="56.496048" + fy="31.701607" + id="radialGradient4528" + xlink:href="#linearGradient3266" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.88267832,0,-2.2566243e-8,1.115007,-69.080446,51.097006)" /> + <clipPath + id="clipPath3754"> + <rect + width="96" + height="96" + x="-100" + y="-3.469447e-15" + id="rect3756" + style="fill:#ffffff;fill-opacity:1;stroke:none" /> + </clipPath> + <linearGradient + x1="45.447727" + y1="92.539597" + x2="45.447727" + y2="7.0165396" + id="ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0058652,0,0,0.994169,100,0)"> + <stop + id="stop3750-8" + style="stop-color:#000000;stop-opacity:1" + offset="0" /> + <stop + id="stop3752-5" + style="stop-color:#000000;stop-opacity:0.58823532" + offset="1" /> + </linearGradient> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3780" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3772" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3725" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3721" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="translate(0,-97)" /> + <linearGradient + x1="32.251034" + y1="6.1317081" + x2="32.251034" + y2="90.238609" + id="linearGradient3811" + xlink:href="#ButtonShadow-0" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0238095,0,0,1.0119048,-1.1428571,-98.071429)" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3277" + id="linearGradient3157" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0513134,0,0,1.0513134,-120.2285,31.416155)" + x1="70.782135" + y1="83.017471" + x2="75.404488" + y2="22.02951" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266" + id="radialGradient3159" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9847961,0.02597927,-0.01823822,0.6913564,1.9937062,24.820256)" + cx="40.846539" + cy="75.263962" + fx="40.846539" + fy="75.263962" + r="14.672466" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266" + id="radialGradient3161" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9847961,0.02597927,-0.01823822,0.6913564,1.9937062,24.820256)" + cx="40.846539" + cy="75.263962" + fx="40.846539" + fy="75.263962" + r="14.672466" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266" + id="radialGradient3163" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.543369,0.28142051,-0.32722971,1.7945958,-138.17549,-6.0460513)" + cx="54.75" + cy="25.072803" + fx="54.75" + fy="25.072803" + r="13" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266" + id="radialGradient3165" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.88267832,0,-2.2566243e-8,1.115007,-69.080446,51.097006)" + cx="56.496048" + cy="31.701607" + fx="56.496048" + fy="31.701607" + r="13" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3277-7" + id="linearGradient3157-9" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0513134,0,0,1.0513134,-120.2285,31.416155)" + x1="70.782135" + y1="83.017471" + x2="75.404488" + y2="22.02951" /> + <linearGradient + id="linearGradient3277-7"> + <stop + id="stop3279-5" + style="stop-color:#3d9119;stop-opacity:1" + offset="0" /> + <stop + id="stop3281-9" + style="stop-color:#76e62b;stop-opacity:1" + offset="1" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266-8" + id="radialGradient3159-7" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9847961,0.02597927,-0.01823822,0.6913564,1.9937062,24.820256)" + cx="40.846539" + cy="75.263962" + fx="40.846539" + fy="75.263962" + r="14.672466" /> + <linearGradient + id="linearGradient3266-8"> + <stop + id="stop3269-5" + style="stop-color:#87ff2b;stop-opacity:1" + offset="0" /> + <stop + id="stop3271-3" + style="stop-color:#87ff2b;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266-8" + id="radialGradient3161-3" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.9847961,0.02597927,-0.01823822,0.6913564,1.9937062,24.820256)" + cx="40.846539" + cy="75.263962" + fx="40.846539" + fy="75.263962" + r="14.672466" /> + <linearGradient + id="linearGradient3196"> + <stop + id="stop3198" + style="stop-color:#87ff2b;stop-opacity:1" + offset="0" /> + <stop + id="stop3200" + style="stop-color:#87ff2b;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266-8" + id="radialGradient3163-8" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.543369,0.28142051,-0.32722971,1.7945958,-138.17549,-6.0460513)" + cx="54.75" + cy="25.072803" + fx="54.75" + fy="25.072803" + r="13" /> + <linearGradient + id="linearGradient3203"> + <stop + id="stop3205" + style="stop-color:#87ff2b;stop-opacity:1" + offset="0" /> + <stop + id="stop3207" + style="stop-color:#87ff2b;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3266-8" + id="radialGradient3165-3" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(0.88267832,0,-2.2566243e-8,1.115007,-69.080446,51.097006)" + cx="56.496048" + cy="31.701607" + fx="56.496048" + fy="31.701607" + r="13" /> + <linearGradient + id="linearGradient3210"> + <stop + id="stop3212" + style="stop-color:#87ff2b;stop-opacity:1" + offset="0" /> + <stop + id="stop3214" + style="stop-color:#87ff2b;stop-opacity:0" + offset="1" /> + </linearGradient> + <radialGradient + r="13" + fy="31.701607" + fx="56.496048" + cy="31.701607" + cx="56.496048" + gradientTransform="matrix(0.88267832,0,-2.2566243e-8,1.115007,-69.080446,51.097006)" + gradientUnits="userSpaceOnUse" + id="radialGradient3222" + xlink:href="#linearGradient3266-8" + inkscape:collect="always" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3386" + id="radialGradient3284" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4750367,0,0,0.847859,-77.736923,-9.8942437)" + cx="53.419292" + cy="66.597893" + fx="53.419292" + fy="66.597893" + r="47.724609" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3386" + id="radialGradient3287" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0199392,0,0,0.85846172,-19.873341,-11.926904)" + cx="53.419292" + cy="66.597893" + fx="53.419292" + fy="66.597893" + r="47.724609" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3386" + id="radialGradient3290" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.4750367,0,0,0.847859,-55.736923,-9.8942437)" + cx="53.419292" + cy="66.597893" + fx="53.419292" + fy="66.597893" + r="47.724609" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3386" + id="radialGradient3293" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0220726,0,0,1.2415079,-19.896446,-47.863009)" + cx="53.419292" + cy="66.597893" + fx="53.419292" + fy="66.597893" + r="47.724609" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3386" + id="radialGradient3296" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0164118,0,0,1.2415079,-19.337623,-31.113008)" + cx="53.419292" + cy="66.597893" + fx="53.419292" + fy="66.597893" + r="47.724609" /> + <radialGradient + inkscape:collect="always" + xlink:href="#linearGradient3386" + id="radialGradient3299" + gradientUnits="userSpaceOnUse" + gradientTransform="matrix(1.0199392,0,0,0.85846172,-19.685841,-9.268213)" + cx="53.419292" + cy="66.597893" + fx="53.419292" + fy="66.597893" + r="47.724609" /> + <linearGradient + inkscape:collect="always" + xlink:href="#linearGradient3187" + id="linearGradient3302" + gradientUnits="userSpaceOnUse" + x1="48" + y1="90" + x2="48" + y2="5.9877172" /> + </defs> + <metadata + id="metadata2413"> + <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></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer2" + style="display:none"> + <rect + width="86" + height="85" + rx="6" + ry="6" + x="5" + y="7" + id="rect3745" + style="opacity:0.9;fill:url(#ButtonShadow);fill-opacity:1;fill-rule:nonzero;stroke:none;filter:url(#filter3174)" /> + </g> + <rect + style="fill:url(#linearGradient3302);fill-opacity:1;fill-rule:nonzero;stroke:none" + id="rect2419" + y="6" + x="6" + ry="6" + rx="6" + height="84" + width="84" /> + <path + style="font-size:6px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.8;fill:url(#radialGradient3299);fill-opacity:1;stroke:none;display:inline;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + id="path3890" + inkscape:connector-curvature="0" + d="m 36.5625,32.0625 c -0.319303,3e-6 -0.56595,0.04413 -0.75,0.125 -0.182658,0.07948 -0.31423,0.171675 -0.40625,0.3125 -0.09063,0.139436 -0.15625,0.311193 -0.15625,0.46875 0,0.239827 0.102775,0.407731 0.28125,0.5625 0.177079,0.154772 0.459488,0.28158 0.875,0.375 0.253766,0.05577 0.43028,0.12476 0.5,0.1875 C 36.97597,34.1565 37,34.23302 37,34.3125 c -2e-6,0.08366 -0.01985,0.15461 -0.09375,0.21875 -0.07251,0.06275 -0.177251,0.09375 -0.3125,0.09375 -0.181264,10e-7 -0.3399,-0.0634 -0.4375,-0.1875 -0.05996,-0.07669 -0.10548,-0.197344 -0.125,-0.34375 l -0.875,0.0625 c 0.02649,0.309543 0.111716,0.580466 0.3125,0.78125 0.200783,0.200784 0.572269,0.28125 1.09375,0.28125 0.296991,0 0.554791,-0.03995 0.75,-0.125 0.195204,-0.08645 0.32874,-0.209074 0.4375,-0.375 0.108757,-0.165925 0.187497,-0.334648 0.1875,-0.53125 -3e-6,-0.167318 -0.04274,-0.333498 -0.125,-0.46875 -0.08087,-0.135248 -0.226384,-0.25312 -0.40625,-0.34375 -0.178477,-0.09202 -0.460885,-0.16076 -0.875,-0.25 C 36.363929,33.09015 36.26337,33.04044 36.21875,33 36.17274,32.96097 36.125,32.9238 36.125,32.875 c 0,-0.06693 0.03798,-0.14148 0.09375,-0.1875 0.05577,-0.0474 0.139846,-0.0625 0.25,-0.0625 0.133854,0 0.2372,0.03101 0.3125,0.09375 0.07669,0.06275 0.13254,0.174464 0.15625,0.3125 l 0.875,-0.0625 C 37.77346,32.650845 37.675108,32.426263 37.46875,32.28125 37.263781,32.134852 36.954306,32.062503 36.5625,32.0625 z m 14.96875,0 c -0.497778,3e-6 -0.877385,0.127386 -1.15625,0.40625 -0.278867,0.278869 -0.4375,0.686937 -0.4375,1.1875 0,0.358345 0.07792,0.63657 0.21875,0.875 0.140827,0.238431 0.336618,0.421098 0.5625,0.53125 0.227275,0.110148 0.497954,0.15625 0.84375,0.15625 0.340215,0 0.616471,-0.06062 0.84375,-0.1875 0.228667,-0.128278 0.411335,-0.302579 0.53125,-0.53125 0.121301,-0.230064 0.187496,-0.516655 0.1875,-0.875 -4e-6,-0.493591 -0.130175,-0.882958 -0.40625,-1.15625 -0.27608,-0.27468 -0.677177,-0.406247 -1.1875,-0.40625 z m 3.375,0 c -0.319304,3e-6 -0.597199,0.04413 -0.78125,0.125 -0.182658,0.07948 -0.31422,0.171675 -0.40625,0.3125 -0.09063,0.139436 -0.125,0.311193 -0.125,0.46875 0,0.239827 0.07153,0.407731 0.25,0.5625 0.17708,0.154772 0.490738,0.28158 0.90625,0.375 0.253767,0.05577 0.39903,0.12476 0.46875,0.1875 0.06972,0.06275 0.124998,0.13927 0.125,0.21875 -2e-6,0.08366 -0.0511,0.15461 -0.125,0.21875 C 55.14624,34.594 55.041498,34.625 54.90625,34.625 54.724985,34.625001 54.5976,34.5616 54.5,34.4375 54.44004,34.36081 54.39452,34.240156 54.375,34.09375 l -0.90625,0.0625 c 0.02649,0.309543 0.142966,0.580466 0.34375,0.78125 0.200783,0.200784 0.572269,0.28125 1.09375,0.28125 0.296991,0 0.523541,-0.03995 0.71875,-0.125 0.195204,-0.08645 0.359989,-0.209074 0.46875,-0.375 0.108756,-0.165925 0.156247,-0.334648 0.15625,-0.53125 -3e-6,-0.167318 -0.04274,-0.333498 -0.125,-0.46875 C 56.04413,33.583502 55.929866,33.46563 55.75,33.375 55.571523,33.28298 55.257865,33.21424 54.84375,33.125 54.676429,33.09015 54.57587,33.04044 54.53125,33 c -0.04602,-0.03903 -0.0625,-0.0762 -0.0625,-0.125 0,-0.06693 0.03798,-0.14148 0.09375,-0.1875 0.05577,-0.0474 0.139847,-0.0625 0.25,-0.0625 0.133855,0 0.2372,0.03101 0.3125,0.09375 0.07669,0.06275 0.10129,0.174464 0.125,0.3125 l 0.90625,-0.0625 c -0.03905,-0.317905 -0.168642,-0.542487 -0.375,-0.6875 -0.204969,-0.146398 -0.483195,-0.218747 -0.875,-0.21875 z M 15,32.125 l 0,3.0625 0.9375,0 0,-1.25 1.1875,0 0,-0.625 -1.1875,0 0,-0.53125 1.40625,0 0,-0.65625 -2.34375,0 z m 3.3125,0 -1.15625,3.0625 0.96875,0 0.125,-0.53125 1.09375,0 0.15625,0.53125 0.96875,0 -1.125,-3.0625 -1.03125,0 z m 2.46875,0 0,3.0625 2.59375,0 0,-0.71875 -1.65625,0 0,-0.59375 1.5,0 0,-0.625 -1.5,0 0,-0.5 1.59375,0 0,-0.625 -2.53125,0 z m 3.09375,0 0,3.0625 0.90625,0 0,-1.6875 1.15625,1.6875 0.875,0 0,-3.0625 -0.875,0 0,1.6875 -1.15625,-1.6875 -0.90625,0 z m 3.5,0 0,0.625 1.53125,0 -1.6875,1.78125 0,0.65625 2.90625,0 0,-0.65625 -1.78125,0 1.71875,-1.8125 0,-0.59375 -2.6875,0 z m 4.03125,0 -1.15625,3.0625 0.96875,0 0.125,-0.53125 1.09375,0 0.15625,0.53125 0.96875,0 -1.125,-3.0625 -1.03125,0 z m 6.78125,0 0,0.75 0.96875,0 0,2.3125 0.9375,0 0,-2.3125 0.96875,0 0,-0.75 -2.875,0 z m 3.3125,0 0,1.8125 c 0,0.150589 0.03519,0.336044 0.09375,0.53125 0.03625,0.121307 0.0899,0.229415 0.1875,0.34375 0.099,0.114335 0.225231,0.18726 0.34375,0.25 0.118517,0.06135 0.261813,0.10409 0.4375,0.125 0.177079,0.02091 0.350804,0.03125 0.5,0.03125 0.257949,0 0.472195,-0.02543 0.65625,-0.09375 0.132459,-0.0488 0.255084,-0.130087 0.375,-0.25 0.121304,-0.121306 0.19422,-0.277152 0.25,-0.4375 0.05716,-0.161742 0.09375,-0.318736 0.09375,-0.5 l 0,-1.8125 -0.9375,0 0,1.84375 c -2e-6,0.170109 -0.06283,0.31283 -0.15625,0.40625 -0.09203,0.09203 -0.211865,0.125 -0.375,0.125 -0.164533,0 -0.28158,-0.03158 -0.375,-0.125 -0.09203,-0.09481 -0.156251,-0.23893 -0.15625,-0.40625 l 0,-1.84375 -0.9375,0 z m 3.59375,0 0,3.0625 1.40625,0 c 0.168713,0 0.354742,-0.03798 0.5625,-0.09375 0.15198,-0.04044 0.273786,-0.128693 0.40625,-0.25 0.132459,-0.1227 0.2386,-0.25763 0.3125,-0.4375 0.07529,-0.181262 0.124997,-0.45358 0.125,-0.78125 0,-0.209148 -0.01231,-0.406908 -0.0625,-0.59375 -0.0502,-0.186838 -0.138456,-0.35917 -0.25,-0.5 -0.111549,-0.140825 -0.266,-0.2372 -0.4375,-0.3125 C 46.986139,32.143459 46.77747,32.125003 46.5,32.125 l -1.40625,0 z m 3.34375,0 0,3.0625 0.9375,0 0,-3.0625 -0.9375,0 z m 3.09375,0.65625 c 0.199387,3e-6 0.353018,0.05365 0.46875,0.1875 0.117126,0.132464 0.187498,0.336376 0.1875,0.625 -2e-6,0.343007 -0.07596,0.58629 -0.1875,0.71875 -0.111549,0.132463 -0.26518,0.21875 -0.46875,0.21875 -0.197997,0 -0.353022,-0.0835 -0.46875,-0.21875 -0.114333,-0.135249 -0.156251,-0.346707 -0.15625,-0.65625 -10e-7,-0.312328 0.04052,-0.552247 0.15625,-0.6875 0.115728,-0.135245 0.277725,-0.187497 0.46875,-0.1875 z m -5.5,0.03125 0.25,0 c 0.245401,3e-6 0.394028,0.03634 0.5,0.15625 0.105963,0.119915 0.187498,0.362622 0.1875,0.6875 0,0.245404 -0.04634,0.421099 -0.09375,0.53125 -0.04741,0.108759 -0.10384,0.17413 -0.1875,0.21875 -0.08366,0.04323 -0.239507,0.0625 -0.4375,0.0625 l -0.21875,0 0,-1.65625 z M 18.8125,32.90625 19.15625,34 l -0.6875,0 0.34375,-1.09375 z m 13.09375,0 L 32.25,34 l -0.6875,0 0.34375,-1.09375 z m -8.875,4.96875 c -0.364643,2e-6 -0.649275,0.05669 -0.84375,0.21875 -0.194472,0.162065 -0.3125,0.417587 -0.3125,0.71875 0,0.240394 0.07964,0.420698 0.21875,0.5625 0.140453,0.141807 0.353732,0.24767 0.65625,0.3125 l 0.3125,0.0625 c 0.183669,0.04051 0.31423,0.07369 0.375,0.125 0.06213,0.05132 0.09375,0.12421 0.09375,0.21875 -2e-6,0.105341 -0.06576,0.19328 -0.15625,0.25 -0.09049,0.05671 -0.204836,0.09375 -0.375,0.09375 -0.167465,0 -0.350282,-0.04243 -0.53125,-0.09375 -0.179621,-0.05267 -0.369375,-0.116109 -0.5625,-0.21875 l 0,0.65625 C 22.099375,40.85283 22.306875,40.90104 22.5,40.9375 22.693123,40.97397 22.870724,41 23.0625,41 c 0.406505,0 0.70907,-0.08794 0.90625,-0.25 0.19852,-0.163412 0.312497,-0.41642 0.3125,-0.75 -3e-6,-0.253896 -0.07695,-0.424746 -0.21875,-0.5625 -0.141807,-0.137752 -0.382472,-0.24497 -0.71875,-0.3125 L 23,39.0625 c -0.158012,-0.03241 -0.25173,-0.08043 -0.3125,-0.125 -0.05942,-0.04592 -0.09375,-0.10647 -0.09375,-0.1875 0,-0.10804 0.03586,-0.19869 0.125,-0.25 0.08913,-0.05131 0.219877,-0.0625 0.40625,-0.0625 0.140453,0 0.310736,-0.0065 0.46875,0.03125 0.158008,0.03782 0.302633,0.11322 0.46875,0.1875 l 0,-0.65625 c -0.187725,-0.04997 -0.355685,-0.06943 -0.53125,-0.09375 -0.17557,-0.02566 -0.333888,-0.03125 -0.5,-0.03125 z m 2.78125,0 c -0.364642,3e-6 -0.649275,0.05669 -0.84375,0.21875 -0.194472,0.162065 -0.281251,0.417587 -0.28125,0.71875 -1e-6,0.240395 0.07965,0.420697 0.21875,0.5625 0.140453,0.141806 0.353733,0.24767 0.65625,0.3125 L 25.875,39.75 c 0.18367,0.04051 0.28298,0.07368 0.34375,0.125 0.06212,0.05132 0.09375,0.12421 0.09375,0.21875 -1e-6,0.105342 -0.03451,0.19329 -0.125,0.25 -0.09049,0.05671 -0.204836,0.09375 -0.375,0.09375 -0.167467,0 -0.350282,-0.04243 -0.53125,-0.09375 -0.17962,-0.05267 -0.369374,-0.11611 -0.5625,-0.21875 l 0,0.65625 c 0.193126,0.07158 0.369375,0.11979 0.5625,0.15625 C 25.474373,40.97397 25.683224,41 25.875,41 c 0.406505,0 0.709071,-0.08794 0.90625,-0.25 0.19852,-0.163412 0.281248,-0.416421 0.28125,-0.75 -2e-6,-0.253897 -0.0457,-0.424746 -0.1875,-0.5625 -0.141807,-0.137752 -0.382472,-0.24497 -0.71875,-0.3125 L 25.8125,39.0625 C 25.654489,39.03009 25.56077,38.98207 25.5,38.9375 25.44058,38.89158 25.40625,38.83103 25.40625,38.75 c -2e-6,-0.10804 0.03586,-0.19869 0.125,-0.25 0.08913,-0.05131 0.219876,-0.0625 0.40625,-0.0625 0.140453,0 0.310737,-0.0066 0.46875,0.03125 0.158009,0.03782 0.302634,0.11322 0.46875,0.1875 L 26.875,38 C 26.687275,37.950031 26.519315,37.93057 26.34375,37.90625 26.168181,37.88059 25.978613,37.875003 25.8125,37.875 z m 6.28125,0 c -0.349448,0.05242 -0.618889,0.196585 -0.84375,0.40625 -0.299816,0.279562 -0.4375,0.668714 -0.4375,1.15625 0,0.482137 0.143086,0.873992 0.4375,1.15625 C 31.544413,40.874658 31.933755,41 32.4375,41 c 0.222834,0 0.446916,-0.01524 0.65625,-0.0625 0.209328,-0.04727 0.399272,-0.12421 0.59375,-0.21875 l 0,-1.46875 -1.21875,0 0,0.53125 0.46875,0 0,0.59375 c -0.05537,0.0216 -0.11727,0.02045 -0.1875,0.03125 -0.06888,0.0095 -0.13772,0.03125 -0.21875,0.03125 -0.298467,10e-7 -0.525439,-0.07578 -0.6875,-0.25 -0.162064,-0.174215 -0.250001,-0.429925 -0.25,-0.75 -1e-6,-0.322772 0.08254,-0.577132 0.25,-0.75 0.168814,-0.174216 0.408129,-0.249998 0.71875,-0.25 0.167463,0 0.333884,0.01524 0.5,0.0625 0.167462,0.04727 0.362433,0.12286 0.53125,0.21875 l 0,-0.625 C 33.430335,38.01947 33.247518,37.94406 33.0625,37.90625 32.878826,37.86844 32.669977,37.875 32.46875,37.875 c -0.130326,10e-7 -0.258517,-0.01747 -0.375,0 z M 15,37.90625 l 0,3.03125 0.75,0 0,-2.21875 0.6875,1.65625 0.5,0 0.6875,-1.65625 0,2.21875 0.75,0 0,-3.03125 -1,0 -0.6875,1.625 -0.6875,-1.625 -1,0 z m 4.125,0 0,3.03125 2.15625,0 0,-0.59375 -1.375,0 0,-0.6875 1.25,0 0,-0.59375 -1.25,0 0,-0.5625 1.34375,0 0,-0.59375 -2.125,0 z m 15.25,0 0,3.03125 2.15625,0 0,-0.59375 -1.375,0 0,-0.6875 1.25,0 0,-0.59375 -1.25,0 0,-0.5625 1.3125,0 0,-0.59375 -2.09375,0 z m -5.84375,0.03125 -1.125,3.03125 0.78125,0 0.1875,-0.5625 1.21875,0 0.1875,0.5625 0.78125,0 -1.125,-3.03125 -0.90625,0 z M 29,38.625 l 0.40625,1.21875 -0.84375,0 L 29,38.625 z" /> + <path + style="font-size:6px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.8;fill:url(#radialGradient3296);fill-opacity:1;stroke:none;display:inline;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + id="path3842" + inkscape:connector-curvature="0" + d="m 40,39 41,0 0,1 -41,0 0,-1 z" /> + <path + style="font-size:6px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.8;fill:url(#radialGradient3293);fill-opacity:1;stroke:none;display:inline;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + id="path3840" + inkscape:connector-curvature="0" + d="m 15,69 66,0 0,1 -66,0 0,-1 z" /> + <path + style="font-size:6px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.8;fill:url(#radialGradient3290);fill-opacity:1;stroke:none;display:inline;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + id="text3348" + inkscape:connector-curvature="0" + d="m 59,70 0,14 -1,0 0,-14 1,0 z" /> + <path + style="font-size:6px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.8;fill:url(#radialGradient3287);fill-opacity:1;stroke:none;display:inline;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + id="path3870" + inkscape:connector-curvature="0" + d="m 41.78125,62.875 c -0.364641,3e-6 -0.649276,0.05669 -0.84375,0.21875 -0.194473,0.162065 -0.28125,0.417586 -0.28125,0.71875 0,0.240395 0.07964,0.420696 0.21875,0.5625 0.140454,0.141805 0.353733,0.24767 0.65625,0.3125 l 0.3125,0.0625 c 0.183669,0.04051 0.28298,0.07368 0.34375,0.125 0.06212,0.05132 0.09375,0.12421 0.09375,0.21875 -2e-6,0.105341 -0.03452,0.19328 -0.125,0.25 -0.09049,0.05671 -0.204835,0.09375 -0.375,0.09375 -0.167466,0 -0.350281,-0.04243 -0.53125,-0.09375 -0.17962,-0.05267 -0.369376,-0.11611 -0.5625,-0.21875 l 0,0.65625 c 0.193124,0.07157 0.369376,0.11979 0.5625,0.15625 0.193125,0.03647 0.401974,0.0625 0.59375,0.0625 0.406504,0 0.709071,-0.08794 0.90625,-0.25 0.19852,-0.163413 0.281247,-0.41642 0.28125,-0.75 -3e-6,-0.253896 -0.0457,-0.424745 -0.1875,-0.5625 C 42.701942,64.299749 42.461277,64.19253 42.125,64.125 L 41.78125,64.0625 C 41.623237,64.03009 41.52952,63.98207 41.46875,63.9375 41.40933,63.891583 41.375,63.83103 41.375,63.75 c 0,-0.10804 0.03586,-0.19868 0.125,-0.25 0.08913,-0.05131 0.219875,-0.0625 0.40625,-0.0625 0.140451,0 0.310736,-0.0066 0.46875,0.03125 0.158008,0.03782 0.302634,0.11322 0.46875,0.1875 l 0,-0.65625 C 42.656025,62.950032 42.488067,62.93057 42.3125,62.90625 42.136931,62.88059 41.947363,62.875003 41.78125,62.875 z m 3.0625,0 C 44.505191,62.92793 44.220809,63.069558 44,63.28125 c -0.294414,0.28091 -0.4375,0.672764 -0.4375,1.15625 0,0.482137 0.143086,0.873991 0.4375,1.15625 C 44.294412,65.874658 44.683754,66 45.1875,66 c 0.168813,0 0.344688,-0.02468 0.5,-0.0625 0.155308,-0.03781 0.294342,-0.08197 0.4375,-0.15625 l 0,-0.625 c -0.144508,0.09859 -0.265799,0.17283 -0.40625,0.21875 -0.140457,0.04592 -0.313442,0.0625 -0.46875,0.0625 -0.278209,10e-7 -0.49689,-0.102981 -0.65625,-0.28125 -0.159363,-0.178269 -0.218751,-0.406778 -0.21875,-0.71875 -10e-7,-0.313321 0.05939,-0.57173 0.21875,-0.75 0.15936,-0.178264 0.378041,-0.249998 0.65625,-0.25 0.155308,0 0.328293,0.01659 0.46875,0.0625 0.140451,0.04592 0.261742,0.12016 0.40625,0.21875 l 0,-0.625 c -0.143158,-0.07428 -0.282192,-0.14969 -0.4375,-0.1875 -0.155312,-0.0378 -0.331187,-0.03125 -0.5,-0.03125 -0.125937,10e-7 -0.230897,-0.01764 -0.34375,0 z m -18.875,0.03125 0,0.59375 1,0 0,2.4375 0.78125,0 0,-2.4375 1,0 0,-0.59375 -2.78125,0 z m 3.1875,0 0,3.03125 2.15625,0 0,-0.59375 -1.375,0 0,-0.6875 1.25,0 0,-0.59375 -1.25,0 0,-0.5625 1.3125,0 0,-0.59375 -2.09375,0 z m 17.625,0 0,3.03125 2.15625,0 0,-0.59375 -1.375,0 0,-0.6875 1.25,0 0,-0.59375 -1.25,0 0,-0.5625 1.3125,0 0,-0.59375 -2.09375,0 z m 2.84375,0 0,3.03125 0.71875,0 0,-2.0625 1.125,2.0625 0.84375,0 0,-3.03125 -0.71875,0 0,2.09375 -1.09375,-2.09375 -0.875,0 z m 3.46875,0 0,3.03125 2.15625,0 0,-0.59375 -1.375,0 0,-0.6875 1.25,0 0,-0.59375 -1.25,0 0,-0.5625 1.3125,0 0,-0.59375 -2.09375,0 z m 11.65625,0 0,0.59375 1,0 0,2.4375 0.78125,0 0,-2.4375 1,0 0,-0.59375 -2.78125,0 z m 6.09375,0 0,3.03125 0.78125,0 0,-1.1875 1.1875,1.1875 0.96875,0 -1.59375,-1.59375 1.4375,-1.4375 -0.90625,0 -1.09375,1.125 0,-1.125 -0.78125,0 z m 3.1875,0 0,3.03125 2.15625,0 0,-0.59375 -1.375,0 0,-0.6875 1.25,0 0,-0.59375 -1.25,0 0,-0.5625 1.34375,0 0,-0.59375 -2.125,0 z M 20,62.9375 l 0,3.03125 0.8125,0 c 0.453773,0 0.80436,-0.06017 1.03125,-0.125 0.226885,-0.06618 0.431684,-0.15584 0.59375,-0.3125 0.141802,-0.136402 0.24362,-0.290479 0.3125,-0.46875 0.06887,-0.179617 0.09375,-0.39676 0.09375,-0.625 -2e-6,-0.225535 -0.02487,-0.415479 -0.09375,-0.59375 C 22.68112,63.665484 22.579302,63.511405 22.4375,63.375 22.276784,63.218343 22.069286,63.09608 21.84375,63.03125 21.619563,62.96508 21.271675,62.9375 20.8125,62.9375 l -0.8125,0 z m 4.1875,0 -1.09375,3.03125 0.78125,0 0.1875,-0.5625 1.21875,0 0.1875,0.5625 0.78125,0 -1.125,-3.03125 -0.9375,0 z m 44.1875,0 -1.125,3.03125 0.78125,0 0.21875,-0.5625 1.21875,0 0.1875,0.5625 0.78125,0 -1.125,-3.03125 -0.9375,0 z m -47.59375,0.59375 0.28125,0 c 0.320071,2e-6 0.551284,0.06209 0.71875,0.21875 0.167457,0.156663 0.249997,0.387686 0.25,0.6875 -3e-6,0.301167 -0.08119,0.52949 -0.25,0.6875 -0.167467,0.158017 -0.400029,0.25 -0.71875,0.25 l -0.28125,0 0,-1.84375 z m 3.875,0.09375 0.4375,1.21875 -0.84375,0 0.40625,-1.21875 z m 44.1875,0 0.40625,1.21875 -0.8125,0 0.40625,-1.21875 z" /> + <path + style="font-size:6px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;opacity:0.8;fill:url(#radialGradient3284);fill-opacity:1;stroke:none;display:inline;font-family:DejaVu Sans;-inkscape-font-specification:DejaVu Sans Bold" + id="path3935" + inkscape:connector-curvature="0" + d="m 37,70 0,14 -1,0 0,-14 1,0 z" /> + <g + id="layer5"> + <path + d="M 12,90 C 8.676,90 6,87.324 6,84 L 6,82 6,14 6,12 c 0,-0.334721 0.04135,-0.6507 0.09375,-0.96875 0.0487,-0.295596 0.09704,-0.596915 0.1875,-0.875 C 6.29113,10.12587 6.302142,10.09265 6.3125,10.0625 6.411365,9.774729 6.5473802,9.515048 6.6875,9.25 6.8320918,8.976493 7.0031161,8.714385 7.1875,8.46875 7.3718839,8.223115 7.5612765,7.995278 7.78125,7.78125 8.221197,7.353194 8.72416,6.966724 9.28125,6.6875 9.559795,6.547888 9.8547231,6.440553 10.15625,6.34375 9.9000482,6.443972 9.6695391,6.580022 9.4375,6.71875 c -0.00741,0.0044 -0.023866,-0.0045 -0.03125,0 -0.031933,0.0193 -0.062293,0.04251 -0.09375,0.0625 -0.120395,0.0767 -0.2310226,0.163513 -0.34375,0.25 -0.1061728,0.0808 -0.2132809,0.161112 -0.3125,0.25 C 8.4783201,7.442683 8.3087904,7.626638 8.15625,7.8125 8.0486711,7.942755 7.9378561,8.077785 7.84375,8.21875 7.818661,8.25713 7.805304,8.30462 7.78125,8.34375 7.716487,8.446782 7.6510225,8.548267 7.59375,8.65625 7.4927417,8.850956 7.3880752,9.071951 7.3125,9.28125 7.30454,9.30306 7.288911,9.3218 7.28125,9.34375 7.2494249,9.4357 7.2454455,9.530581 7.21875,9.625 7.1884177,9.731618 7.1483606,9.828031 7.125,9.9375 7.0521214,10.279012 7,10.635705 7,11 l 0,2 0,68 0,2 c 0,2.781848 2.2181517,5 5,5 l 2,0 68,0 2,0 c 2.781848,0 5,-2.218152 5,-5 l 0,-2 0,-68 0,-2 C 89,10.635705 88.94788,10.279012 88.875,9.9375 88.83085,9.730607 88.78662,9.539842 88.71875,9.34375 88.71105,9.3218 88.69545,9.30306 88.6875,9.28125 88.62476,9.107511 88.549117,8.913801 88.46875,8.75 88.42717,8.6672 88.38971,8.580046 88.34375,8.5 88.28915,8.40279 88.216976,8.31165 88.15625,8.21875 88.06214,8.077785 87.951329,7.942755 87.84375,7.8125 87.700576,7.63805 87.540609,7.465502 87.375,7.3125 87.36383,7.3023 87.35502,7.29135 87.34375,7.28125 87.205364,7.155694 87.058659,7.046814 86.90625,6.9375 86.803679,6.86435 86.701932,6.784136 86.59375,6.71875 c -0.0074,-0.0045 -0.02384,0.0044 -0.03125,0 -0.232039,-0.138728 -0.462548,-0.274778 -0.71875,-0.375 0.301527,0.0968 0.596455,0.204138 0.875,0.34375 0.55709,0.279224 1.060053,0.665694 1.5,1.09375 0.219973,0.214028 0.409366,0.441865 0.59375,0.6875 0.184384,0.245635 0.355408,0.507743 0.5,0.78125 0.14012,0.265048 0.276135,0.524729 0.375,0.8125 0.01041,0.03078 0.02133,0.06274 0.03125,0.09375 0.09046,0.278085 0.1388,0.579404 0.1875,0.875 C 89.95865,11.3493 90,11.665279 90,12 l 0,2 0,68 0,2 c 0,3.324 -2.676,6 -6,6 l -72,0 z" + inkscape:connector-curvature="0" + id="path3615" + style="opacity:0.2;fill:url(#radialGradient3619);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <rect + width="66" + height="66" + rx="12" + ry="12" + x="15" + y="15" + clip-path="url(#clipPath3613)" + id="rect3171" + style="opacity:0.1;fill:url(#linearGradient3613);fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3794)" /> + </g> + <g + id="layer3"> + <path + d="M 12,6 C 8.676,6 6,8.676 6,12 l 0,12 84,0 0,-12 C 90,8.676 87.324,6 84,6 L 12,6 z" + inkscape:connector-curvature="0" + id="rect4237" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <rect + width="84" + height="6" + x="6" + y="24" + id="rect3250" + style="opacity:0.8;fill:url(#linearGradient4262);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <rect + width="84" + height="5" + x="6" + y="15" + id="rect4289" + style="opacity:0.3;fill:url(#linearGradient4320);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <g + transform="translate(1,0)" + id="g4299"> + <path + d="M 28.333333,6 23,15 28.333333,24 39,24 33.666667,15 39,6 28.333333,6 z" + inkscape:connector-curvature="0" + id="path4293" + style="fill:#f0f0f0;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + d="M 50.333333,6 45,15 50.333333,24 61,24 55.666667,15 61,6 50.333333,6 z" + inkscape:connector-curvature="0" + id="path4295" + style="fill:#f0f0f0;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + d="M 72.333333,6 67,15 72.333333,24 83,24 77.666667,15 83,6 72.333333,6 z" + inkscape:connector-curvature="0" + id="path4297" + style="fill:#f0f0f0;fill-opacity:1;fill-rule:evenodd;stroke:none" /> + </g> + <rect + width="84" + height="5" + x="6" + y="10" + id="rect4291" + style="opacity:0.7;fill:url(#linearGradient4310);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <rect + width="84" + height="5" + x="6" + y="19" + id="rect4324" + style="opacity:0.7;fill:url(#linearGradient4326);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + d="m 12.005391,10.5 c 1.109513,0 1.770155,0.983693 6.03003,4.302704 4.304387,3.353689 5.477493,3.726472 5.477493,5.074645 0,1.348423 -1.088205,1.622651 -2.439921,1.622651 l -8.133072,0 C 11.588205,21.5 10.5,20.414446 10.5,19.066023 l 0,-6.490605 C 10.5,11.226995 10.967611,10.5 12.005391,10.5 z" + inkscape:connector-curvature="0" + id="path4333" + style="fill:url(#linearGradient4371);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient4373);stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" /> + <path + d="m 12.75,14.9375 a 1.4375,1.4375 0 1 1 -2.875,0 1.4375,1.4375 0 1 1 2.875,0 z" + transform="matrix(0.81330712,0,0,0.81132563,3.5868895,1.0746776)" + id="path4335" + style="fill:url(#radialGradient4379);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + d="m 12.75,14.9375 a 1.4375,1.4375 0 1 1 -2.875,0 1.4375,1.4375 0 1 1 2.875,0 z" + transform="matrix(0.81330712,0,0,0.81132563,3.5868895,7.09897)" + id="path4337" + style="fill:url(#radialGradient4377);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + <path + d="m 12.75,14.9375 a 1.4375,1.4375 0 1 1 -2.875,0 1.4375,1.4375 0 1 1 2.875,0 z" + transform="matrix(0.81330712,0,0,0.81132563,11.618297,7.09897)" + id="path4339" + style="fill:url(#radialGradient4375);fill-opacity:1;fill-rule:evenodd;stroke:none" /> + </g> + <g + id="layer4"> + <path + d="M 12,6 C 8.676,6 6,8.676 6,12 l 0,2 0,68 0,2 c 0,0.334721 0.04135,0.6507 0.09375,0.96875 0.0487,0.295596 0.09704,0.596915 0.1875,0.875 0.00988,0.03038 0.020892,0.0636 0.03125,0.09375 0.098865,0.287771 0.2348802,0.547452 0.375,0.8125 0.1445918,0.273507 0.3156161,0.535615 0.5,0.78125 0.1843839,0.245635 0.3737765,0.473472 0.59375,0.6875 0.439947,0.428056 0.94291,0.814526 1.5,1.09375 0.278545,0.139612 0.5734731,0.246947 0.875,0.34375 -0.2562018,-0.100222 -0.4867109,-0.236272 -0.71875,-0.375 -0.00741,-0.0044 -0.023866,0.0045 -0.03125,0 -0.031933,-0.0193 -0.062293,-0.04251 -0.09375,-0.0625 -0.120395,-0.0767 -0.2310226,-0.163513 -0.34375,-0.25 -0.1061728,-0.0808 -0.2132809,-0.161112 -0.3125,-0.25 C 8.4783201,88.557317 8.3087904,88.373362 8.15625,88.1875 8.0486711,88.057245 7.9378561,87.922215 7.84375,87.78125 7.818661,87.74287 7.805304,87.69538 7.78125,87.65625 7.716487,87.553218 7.6510225,87.451733 7.59375,87.34375 7.4927417,87.149044 7.3880752,86.928049 7.3125,86.71875 7.30454,86.69694 7.288911,86.6782 7.28125,86.65625 7.2494249,86.5643 7.2454455,86.469419 7.21875,86.375 7.1884177,86.268382 7.1483606,86.171969 7.125,86.0625 7.0521214,85.720988 7,85.364295 7,85 L 7,83 7,15 7,13 C 7,10.218152 9.2181517,8 12,8 l 2,0 68,0 2,0 c 2.781848,0 5,2.218152 5,5 l 0,2 0,68 0,2 c 0,0.364295 -0.05212,0.720988 -0.125,1.0625 -0.04415,0.206893 -0.08838,0.397658 -0.15625,0.59375 -0.0077,0.02195 -0.0233,0.04069 -0.03125,0.0625 -0.06274,0.173739 -0.138383,0.367449 -0.21875,0.53125 -0.04158,0.0828 -0.07904,0.169954 -0.125,0.25 -0.0546,0.09721 -0.126774,0.18835 -0.1875,0.28125 -0.09411,0.140965 -0.204921,0.275995 -0.3125,0.40625 -0.143174,0.17445 -0.303141,0.346998 -0.46875,0.5 -0.01117,0.0102 -0.01998,0.02115 -0.03125,0.03125 -0.138386,0.125556 -0.285091,0.234436 -0.4375,0.34375 -0.102571,0.07315 -0.204318,0.153364 -0.3125,0.21875 -0.0074,0.0045 -0.02384,-0.0044 -0.03125,0 -0.232039,0.138728 -0.462548,0.274778 -0.71875,0.375 0.301527,-0.0968 0.596455,-0.204138 0.875,-0.34375 0.55709,-0.279224 1.060053,-0.665694 1.5,-1.09375 0.219973,-0.214028 0.409366,-0.441865 0.59375,-0.6875 0.184384,-0.245635 0.355408,-0.507743 0.5,-0.78125 0.14012,-0.265048 0.276135,-0.524729 0.375,-0.8125 0.01041,-0.03078 0.02133,-0.06274 0.03125,-0.09375 0.09046,-0.278085 0.1388,-0.579404 0.1875,-0.875 C 89.95865,84.6507 90,84.334721 90,84 l 0,-2 0,-68 0,-2 C 90,8.676 87.324,6 84,6 L 12,6 z" + inkscape:connector-curvature="0" + id="rect3728" + style="opacity:0.3;fill:url(#linearGradient3188);fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + id="g4513" + transform="matrix(0.6394564,0,0,0.6394564,84.664912,2.0456889)"> + <path + style="fill:url(#linearGradient3157-9);fill-opacity:1;stroke:#34870e;stroke-width:2.34574246;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path3261" + inkscape:connector-curvature="0" + d="m -65.015175,50.278074 0,54.903746 c -3.855793,-1.50998 -8.894464,-1.76801 -14.09417,-0.36139 -9.717741,2.62883 -16.233352,10.00877 -14.521267,16.45962 1.712085,6.45086 10.979991,9.56093 20.697733,6.9321 8.256133,-2.23343 14.170779,-7.8963 14.718388,-13.50281 l 0.06571,0 0,-40.377001 35.186145,4.369521 0,39.09572 c -3.855791,-1.50998 -8.894464,-1.76801 -14.09417,-0.36139 -9.717739,2.62883 -16.233352,10.00876 -14.521267,16.45962 1.712087,6.45086 10.979991,9.56093 20.697733,6.9321 8.256135,-2.23343 14.170779,-7.8963 14.718388,-13.50281 l 0.06571,0 0,-70.542025 -48.918927,-6.505001 z m 6.866391,13.212595 35.186145,4.960885 0,4.435229 -35.186145,-4.369522 0,-5.026592 z" /> + <path + inkscape:connector-curvature="0" + style="fill:url(#radialGradient3159-7);fill-opacity:1;stroke:none" + id="path2494" + transform="matrix(1.0233043,-0.24105639,0.24105639,1.0233043,-138.19892,40.809487)" + d="m 56.391766,82.480003 a 14.672467,9.2807773 0 1 1 -29.344933,0 14.672467,9.2807773 0 1 1 29.344933,0 z" /> + <path + inkscape:connector-curvature="0" + style="fill:url(#radialGradient3161-3);fill-opacity:1;stroke:none" + id="path3278" + transform="matrix(1.0233043,-0.24105639,0.24105639,1.0233043,-96.754882,53.447131)" + d="m 56.391766,82.480003 a 14.672467,9.2807773 0 1 1 -29.344933,0 14.672467,9.2807773 0 1 1 29.344933,0 z" /> + <path + style="fill:none;stroke:url(#radialGradient3163-8);stroke-width:3.12765646;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path3282" + inkscape:connector-curvature="0" + d="m -61.35495,88.196416 0,-33.510614 24.18021,3.942425" /> + <path + style="fill:none;stroke:url(#radialGradient3222);stroke-width:4.93222046;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" + id="path3292" + inkscape:connector-curvature="0" + d="m -19.212614,107.89627 0,-42.617148" /> + </g> +</svg> diff --git a/rapid/glade3/video24.png b/rapid/glade3/video24.png Binary files differdeleted file mode 100644 index df8b22b..0000000 --- a/rapid/glade3/video24.png +++ /dev/null diff --git a/rapid/glade3/video66.png b/rapid/glade3/video66.png Binary files differnew file mode 100644 index 0000000..5502609 --- /dev/null +++ b/rapid/glade3/video66.png diff --git a/rapid/glade3/video_small.png b/rapid/glade3/video_small.png Binary files differdeleted file mode 100644 index 74e7c0f..0000000 --- a/rapid/glade3/video_small.png +++ /dev/null diff --git a/rapid/glade3/video_small_shadow.png b/rapid/glade3/video_small_shadow.png Binary files differdeleted file mode 100644 index bf39c21..0000000 --- a/rapid/glade3/video_small_shadow.png +++ /dev/null diff --git a/rapid/gnomeglade.py b/rapid/gnomeglade.py deleted file mode 100644 index c0b0860..0000000 --- a/rapid/gnomeglade.py +++ /dev/null @@ -1,166 +0,0 @@ -### 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/idletube.py b/rapid/idletube.py deleted file mode 100644 index 0b07536..0000000 --- a/rapid/idletube.py +++ /dev/null @@ -1,205 +0,0 @@ - -# Copyright (c) 2005 Antoon Pardon -# -# Modified 2010 by Damon Lynch to use python's higher performance deque, rather than a regular list -# -# 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. - - -import collections -from Queue import Queue - -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 = collections.deque() - - def put(self, item): - self.fifo.append(item) - - def get(self): - return self.fifo.popleft() - - 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) - if len(self.writers) == 0: - if self.container.size() == 0: - self.empty.release() - if self.cb_src is Registered and len(self.readers) > 0: - self.cb_src = gob.idle_add(self._idle_callback) - for _ in self.readers: - 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: - self.cb_src = gob.idle_add(self._idle_callback) - 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 - import gobject as gob - - 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 deleted file mode 100755 index 9819ab7..0000000 --- a/rapid/media.py +++ /dev/null @@ -1,339 +0,0 @@ -#!/usr/bin/python -# -*- coding: latin1 -*- - -### Copyright (C) 2007, 2008, 2009, 2010 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 types -import datetime -import subprocess - -import config -from config import max_thumbnail_size -from config import STATUS_NOT_DOWNLOADED, \ - STATUS_DOWNLOAD_PENDING, \ - STATUS_CANNOT_DOWNLOAD - - -import common -import metadata -import videometadata - -from common import Configi18n -global _ -_ = Configi18n._ - -import operator -import gtk - -def _getDefaultLocationLegacy(options, ignore_missing_dir=False): - if ignore_missing_dir: - return common.getFullPath(options[0]) - for default in options: - path = common.getFullPath(default) - if os.path.isdir(path): - return path - return common.getFullPath('') - -def _getDefaultLocationXDG(dir_type): - proc = subprocess.Popen(['xdg-user-dir', dir_type], stdout=subprocess.PIPE) - output = proc.communicate()[0].strip() - return output - -def getDefaultPhotoLocation(ignore_missing_dir=False): - try: - return _getDefaultLocationXDG('PICTURES') - except: - return _getDefaultLocationLegacy(config.DEFAULT_PHOTO_LOCATIONS, ignore_missing_dir) - -def getDefaultVideoLocation(ignore_missing_dir=False): - try: - return _getDefaultLocationXDG('VIDEOS') - except: - return _getDefaultLocationLegacy(config.DEFAULT_VIDEO_LOCATIONS, ignore_missing_dir) - -def getDefaultBackupPhotoIdentifier(): - return os.path.split(getDefaultPhotoLocation(ignore_missing_dir = True))[1] - -def getDefaultBackupVideoIdentifier(): - return os.path.split(getDefaultVideoLocation(ignore_missing_dir = True))[1] - -def is_DCIM_Media(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, identifiers, writeable=True): - """ Test to see if path is used as a backup medium for storing photos or videos - - Identifiers is expected to be a list of folder names to check to see - if the path is a backup path. Only one of them needs to be present - for the path to be considered a backup medium. - - If writeable is True, the directory must be writeable by the user """ - suitable = False - - for identifier in identifiers: - 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 - if suitable: - return True - return False - -def isImage(fileName): - ext = os.path.splitext(fileName)[1].lower()[1:] - return (ext in metadata.RAW_FILE_EXTENSIONS) or (ext in metadata.NON_RAW_IMAGE_FILE_EXTENSIONS) - -def isVideo(fileName): - ext = os.path.splitext(fileName)[1].lower()[1:] - return (ext in videometadata.VIDEO_FILE_EXTENSIONS) - - -class MediaFile: - """ - A photo or video file, with metadata - """ - - def __init__(self, thread_id, name, path, size, fileSystemModificationTime, deviceName, downloadFolder, volume, isPhoto = True): - self.thread_id = thread_id - self.path = path - self.name = name - self.fullFileName = os.path.join(path, name) - self.size = size # type int - self.modificationTime = fileSystemModificationTime - self.deviceName = deviceName - self.downloadFolder = downloadFolder - self.volume = volume - - self.jobcode = '' - - # a reference into the SelectionTreeView's liststore - self.treerowref = None - - # generated values - self.downloadSubfolder = '' - self.downloadPath = '' - self.downloadName = '' - self.downloadFullFileName = '' - - self.isImage = isPhoto - self.isVideo = not self.isImage - if isPhoto: - self.displayName = _("photo") - self.displayNameCap = _("Photo") - else: - self.displayName = _("video") - self.displayNameCap = _("Video") - - - self.metadata = None - self.thumbnail = None - self.genericThumbnail = False - self.sampleName = '' - self.sampleSubfolder = '' - self.samplePath = '' - - # whether the sample genereated name, subfolder and path need to be refreshed in a preview - self.sampleStale = False - - self.status = STATUS_NOT_DOWNLOADED - self.problem = None # class Problem in problemnotifcation.py - - def loadMetadata(self): - """ - Attempt to load the metadata for the photo or video - - Raises errors if unable to be loaded - """ - if not self.metadata: - if self.isImage: - self.metadata = metadata.MetaData(self.fullFileName) - self.metadata.read() - else: - self.metadata = videometadata.VideoMetaData(self.fullFileName) - - - def dateTime(self, alternative_if_date_missing=None): - date = None - if self.metadata: - date = self.metadata.dateTime() - if not date: - if alternative_if_date_missing: - date = alternative_if_date_missing - else: - date = datetime.datetime.fromtimestamp(self.modificationTime) - return date - - - def generateThumbnail(self, tempWorkingDir): - """ - Attempts to generate or extract a thumnail and its orientation for the photo or video - """ - if self.metadata is None: - sys.stderr.write("metadata should not be empty!") - else: - if self.isImage: - try: - thumbnail = self.metadata.getThumbnailData(max_thumbnail_size) - if not isinstance(thumbnail, types.StringType): - self.thumbnail = None - else: - orientation = self.metadata.orientation(missing=None) - pbloader = gtk.gdk.PixbufLoader() - pbloader.write(thumbnail) - pbloader.close() - # Get the resulting pixbuf and build an image to be displayed - pixbuf = pbloader.get_pixbuf() - if orientation == 8: - pixbuf = pixbuf.rotate_simple(gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE) - elif orientation == 6: - pixbuf = pixbuf.rotate_simple(gtk.gdk.PIXBUF_ROTATE_CLOCKWISE) - elif orientation == 3: - pixbuf = pixbuf.rotate_simple(gtk.gdk.PIXBUF_ROTATE_UPSIDEDOWN) - - self.thumbnail = pixbuf - except: - pass - else: - # get thumbnail of video - # it may need to be generated - self.thumbnail = self.metadata.getThumbnailData(max_thumbnail_size, tempWorkingDir) - if self.thumbnail: - # scale to size - self.thumbnail = common.scale2pixbuf(max_thumbnail_size, max_thumbnail_size, self.thumbnail) - - - -class Media: - """ Generic class for media holding images and videos """ - def __init__(self, path, volume = None): - """ - volume is a gnomevfs or gio volume: see class Volume in rapid.py - """ - - 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, hard drives, etc.""" - def __init__(self, path, volume = None): - """ - volume is a gnomevfs or gio volume, see class Volume in rapid.py - """ - Media.__init__(self, path, volume) - - - def setMedia(self, imagesAndVideos, fileSizeSum, noFiles): - self.imagesAndVideos = imagesAndVideos # class MediaFile - self.fileSizeSum = fileSizeSum - self.noFiles = noFiles - - def numberOfImagesAndVideos(self): - return self.noFiles - - def sizeOfImagesAndVideos(self, humanReadable = True): - if humanReadable: - return common.formatSizeForUser(self.fileSizeSum) - else: - return self.fileSizeSum - - def sizeAndNumberDownloadPending(self): - """ - Returns how many files have their status set to download pending, and their size - """ - v = s = 0 - fileIndex = [] - for i in range(len(self.imagesAndVideos)): - mediaFile = self.imagesAndVideos[i][0] - if mediaFile.status == STATUS_DOWNLOAD_PENDING: - v += 1 - s += mediaFile.size - fileIndex.append(i) - return (v, s, fileIndex) - - def numberOfFilesNotCannotDownload(self): - """ - Returns how many files whose status is not cannot download - """ - v = 0 - for i in range(len(self.imagesAndVideos)): - mediaFile = self.imagesAndVideos[i][0] - if mediaFile.status <> STATUS_CANNOT_DOWNLOAD: - v += 1 - - return v - - def downloadPending(self): - """ - Returns true if there a mediaFile with status download pending on the device. - Inefficient. Not currently used. - """ - for i in range(len(self.imagesAndVideos)): - mediaFile = self.imagesAndVideos[i][0] - if mediaFile.status == config.STATUS_DOWNLOAD_PENDING: - return True - return False - - def _firstFile(self, isImage): - if self.imagesAndVideos: - for i in range(len(self.imagesAndVideos)): - if self.imagesAndVideos[i][0].isImage == isImage: - return self.imagesAndVideos[i][0] - else: - return None - - def firstImage(self): - return self._firstFile(True) - - def firstVideo(self): - return self._firstFile(False) - diff --git a/rapid/metadata.py b/rapid/metadataphoto.py index 1a040f3..8a760c4 100755 --- a/rapid/metadata.py +++ b/rapid/metadataphoto.py @@ -20,7 +20,7 @@ import re import datetime import sys -import subprocess +#~ import subprocess import config import types import time @@ -31,50 +31,7 @@ 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.1 does not use the "Rational" class -if 'Rational' in dir(pyexiv2): - usesRational = True -else: - usesRational = False -#get versions of pyexiv2 and exiv2 libraries -if 'version_info' in dir(pyexiv2): - pyexiv2_version = pyexiv2.version_info - exiv2_version = pyexiv2.exiv2_version_info - baseclass = eval('pyexiv2.metadata.ImageMetadata') -else: - pyexiv2_version = (0,1,'x') - # try to determine the version of exiv2 from it's standard output - try: - proc = subprocess.Popen(['exiv2', '-V'], stdout=subprocess.PIPE) - output = proc.communicate()[0] - except: - output = None - exiv2_version = None - if output: - # assume output contains the line 'exiv2 0.x' or possibly - # 'exiv2 0.x.x' - start = output.find('exiv2 ') - if start < 0: - exiv2_version = None - else: - end = output.find('\n', start) - if end: - exiv2_v = output[6:end] - else: - exiv2_v = output[6:] - - exiv2_version = [] - dot = exiv2_v.find('.') - while dot > 0: - exiv2_version += [int(exiv2_v[:dot])] - exiv2_v = exiv2_v[dot+1:] - dot = exiv2_v.find('.') - exiv2_version += [int(exiv2_v)] - exiv2_version = tuple(exiv2_version) - - - baseclass = eval('pyexiv2.Image') def __version_info(version): if not version: @@ -85,46 +42,19 @@ def __version_info(version): v += '.%s' % i return v[1:] -def version_info(): - return __version_info(pyexiv2_version) +def pyexiv2_version_info(): + return __version_info(pyexiv2.version_info) def exiv2_version_info(): - return __version_info(exiv2_version) - -RAW_FILE_EXTENSIONS = ['arw', 'dcr', 'cr2', 'crw', 'dng', 'mos', 'mrw', - 'nef', 'orf', 'pef', 'raf', 'raw', 'sr2', 'srw'] - -#exiv2 0.18.1 introduces support for Panasonic .RW2 files -#pyexiv2 in combination with exiv2 0.18 segfaults when trying to read an -#RW2 files, so we should not read those! exiv2 0.17 & pyexiv2 segfaults -#with MEF files. - -if exiv2_version is not None: - if exiv2_version[0] > 0: - RAW_FILE_EXTENSIONS += ['rw2', 'mef'] - else: - if exiv2_version[1] > 17: - RAW_FILE_EXTENSIONS += ['mef'] - if exiv2_version[1] > 18: - RAW_FILE_EXTENSIONS += ['rw2'] - else: - if len(exiv2_version) > 2: - if exiv2_version[2] >= 1: - RAW_FILE_EXTENSIONS += ['rw2'] - -RAW_FILE_EXTENSIONS.sort() - -NON_RAW_IMAGE_FILE_EXTENSIONS = ['jpg', 'jpe', 'jpeg', 'tif', 'tiff'] + return __version_info(pyexiv2.exiv2_version_info) -class MetaData(baseclass): +class MetaData(pyexiv2.metadata.ImageMetadata): """ Class providing human readable access to image metadata """ - __version01__ = pyexiv2_version[0] == 0 and pyexiv2_version[1] == 1 - def aperture(self, missing=''): """ Returns in string format the floating point value of the image's aperture. @@ -133,12 +63,10 @@ class MetaData(baseclass): """ 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) + + a = self["Exif.Photo.FNumber"].value + + a = float(a.numerator) / float(a.denominator) return "%.1f" % a except: return missing @@ -150,11 +78,11 @@ class MetaData(baseclass): Returns missing if the metadata value is not present. """ try: - return "%s" % (self["Exif.Photo.ISOSpeedRatings"]) + return self["Exif.Photo.ISOSpeedRatings"].human_value except: return missing - def exposureTime(self, alternativeFormat=False, missing=''): + def exposure_time(self, alternativeFormat=False, missing=''): """ Returns in string format the exposure time of the image. @@ -180,20 +108,12 @@ class MetaData(baseclass): """ try: - if usesRational: - e = str(self["Exif.Photo.ExposureTime"]) + e = self["Exif.Photo.ExposureTime"].value + + e0 = int(e.numerator) + e1 = int(e.denominator) - e0, e1 = e.split('/') - e0 = int(e0) - e1 = int(e1) - # some values, e.g. Nikon, are in the format "10/1600" - if (e0 > 1) and (e0 < e1): - e1 = e1 / e0 - e0 = 1 - else: - e0, e1 = self["Exif.Photo.ExposureTime"] - if e1 > e0: if alternativeFormat: if e0 == 1: @@ -213,101 +133,93 @@ class MetaData(baseclass): except: return missing - def focalLength(self, missing=''): + def focal_length(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"] + f = self["Exif.Photo.FocalLength"].value + f0 = float(f.numerator) + f1 = float(f.denominator) - f0 = float(f0) - if not f1: - f1 = 1.0 - else: - f1 = float(f1) - return "%.0f" % (f0 / f1) except: return missing - def cameraMake(self, missing=''): + def camera_make(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() + return self["Exif.Image.Make"].value.strip() except: return missing - def cameraModel(self, missing=''): + def camera_model(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() + return self["Exif.Image.Model"].value.strip() except: return missing - def cameraSerial(self, missing=''): + def camera_serial(self, missing=''): try: - keys = self.rpd_keys() + keys = self.exif_keys if 'Exif.Canon.SerialNumber' in keys: - v = self['Exif.Canon.SerialNumber'] + v = self['Exif.Canon.SerialNumber'].raw_value elif 'Exif.Nikon3.SerialNumber' in keys: - v = self['Exif.Nikon3.SerialNumber'] + v = self['Exif.Nikon3.SerialNumber'].raw_value elif 'Exif.OlympusEq.SerialNumber' in keys: - v = self['Exif.OlympusEq.SerialNumber'] + v = self['Exif.OlympusEq.SerialNumber'].raw_value elif 'Exif.Olympus.SerialNumber' in keys: - v = self['Exif.Olympus.SerialNumber'] + v = self['Exif.Olympus.SerialNumber'].raw_value elif 'Exif.Olympus.SerialNumber2' in keys: - v = self['Exif.Olympus.SerialNumber2'] + v = self['Exif.Olympus.SerialNumber2'].raw_value elif 'Exif.Panasonic.SerialNumber' in keys: - v = self['Exif.Panasonic.SerialNumber'] + v = self['Exif.Panasonic.SerialNumber'].raw_value elif 'Exif.Fujifilm.SerialNumber' in keys: - v = self['Exif.Fujifilm.SerialNumber'] + v = self['Exif.Fujifilm.SerialNumber'].raw_value elif 'Exif.Image.CameraSerialNumber' in keys: - v = self['Exif.Image.CameraSerialNumber'] + v = self['Exif.Image.CameraSerialNumber'].raw_value else: return missing - v = str(v) + v = str(v) # probably not necessary, but just in case return v.strip() except: return missing - def shutterCount(self, missing=''): + def shutter_count(self, missing=''): try: - keys = self.rpd_keys() + keys = self.exif_keys if 'Exif.Nikon3.ShutterCount' in keys: - v = self['Exif.Nikon3.ShutterCount'] + v = self['Exif.Nikon3.ShutterCount'].raw_value elif 'Exif.Canon.FileNumber' in keys: - v = self['Exif.Canon.FileNumber'] + v = self['Exif.Canon.FileNumber'].raw_value elif 'Exif.Canon.ImageNumber' in keys: - v = self['Exif.Canon.ImageNumber'] + v = self['Exif.Canon.ImageNumber'].raw_value else: return missing return str(v) except: return missing - def ownerName(self, missing=''): + def owner_name(self, missing=''): """ returns camera name recorded by select Canon cameras""" try: - return self['Exif.Canon.OwnerName'].strip() + return self['Exif.Canon.OwnerName'].value.strip() except: return missing - def shortCameraModel(self, includeCharacters = '', missing=''): + def short_camera_model(self, includeCharacters = '', missing=''): """ Returns in shorterned string format the camera model used to record the image. @@ -359,7 +271,7 @@ class MetaData(baseclass): Note: assume exif values are in ENGLISH, regardless of current platform """ - m = self.cameraModel() + m = self.camera_model() 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]*)"\ @@ -372,25 +284,9 @@ class MetaData(baseclass): return model else: return missing - - def filterMangledDates(self, d): - """ - Some EXIF dates are badly formed. Try to fix them - """ - - _datetime = d.strip() - # remove any weird characters at the end of the string - while _datetime and not _datetime[-1].isdigit(): - _datetime = _datetime[:-1] - _date, _time = _datetime.split(' ') - _datetime = "%s %s" % (_date.replace(":", "-") , _time.replace("-", ":")) - try: - d = datetime.datetime.strptime(_datetime, '%Y-%m-%d %H:%M:%S') - except: - d = None - return d + - def dateTime(self, missing=''): + def date_time(self, missing=''): """ Returns in python datetime format the date and time the image was recorded. @@ -400,22 +296,18 @@ class MetaData(baseclass): Returns missing either metadata value is not present. """ - keys = self.rpd_keys() try: - if "Exif.Photo.DateTimeOriginal" in keys: - v = self["Exif.Photo.DateTimeOriginal"] + if "Exif.Photo.DateTimeOriginal" in self.exif_keys: + v = self["Exif.Photo.DateTimeOriginal"].value else: - v = self["Exif.Image.DateTime"] - if isinstance(v, types.StringType): - v = self.filterMangledDates(v) - if v is None: - v = missing + v = self["Exif.Image.DateTime"].value + return v except: return missing - def timeStamp(self, missing=''): - dt = self.dateTime(missing=None) + def time_stamp(self, missing=''): + dt = self.date_time(missing=None) if not dt is None: try: t = dt.timetuple() @@ -426,10 +318,10 @@ class MetaData(baseclass): ts = missing return ts - def subSeconds(self, missing='00'): + def sub_seconds(self, missing='00'): """ returns the subsecond the image was taken, as recorded by the camera""" try: - return str(self["Exif.Photo.SubSecTimeOriginal"]) + return str(self["Exif.Photo.SubSecTimeOriginal"].value) except: return missing @@ -439,66 +331,13 @@ class MetaData(baseclass): Return type int """ try: - v = self['Exif.Image.Orientation'] + v = self['Exif.Image.Orientation'].value if isinstance(v, types.StringType): - # pyexiv2 >= 0.2 returns a string, not an int v = int(v) return v except: return missing - # following class methods are designed to cope with using both - # pyexiv2 0.1.x and pyexiv2 0.2.x - - def getThumbnailData(self, max_size_needed=0): - """ - Returns a thumbnail of the image. - - If the image supports multiple thumbnails, and max_size_needed - is not 0, then it will search for the smallest thumbnail that - matches the size required - - The image will be in whatever format the thumbnail itself is, - typically a jpeg or tiff. - """ - if self.__version01__: - return pyexiv2.Image.getThumbnailData(self)[1] - - else: - if not self.previews: - return None, None - else: - if max_size_needed: - for thumbnail in self.previews: - if thumbnail.dimensions[0] >= max_size_needed or thumbnail.dimensions[1] >= max_size_needed: - break - else: - thumbnail = self.previews[-1] - - return thumbnail.data - - def read(self): - if self.__version01__: - self.readMetadata() - else: - pyexiv2.metadata.ImageMetadata.read(self) - - def rpd_keys(self): - if self.__version01__: - return pyexiv2.Image.exifKeys(self) - else: - return self.exif_keys - - def __getitem__(self, key): - if self.__version01__: - v = pyexiv2.Image.__getitem__(self, key) - else: - v = pyexiv2.metadata.ImageMetadata.__getitem__(self, key).raw_value - # strip out null bytes from strings - if isinstance(v, types.StringType): - v = v.replace('\x00', '') - return v - class DummyMetaData(MetaData): """ @@ -522,34 +361,34 @@ class DummyMetaData(MetaData): def iso(self, missing=''): return "100" - def exposureTime(self, alternativeFormat=False, missing=''): + def exposure_time(self, alternativeFormat=False, missing=''): if alternativeFormat: return "4000" else: return "1/4000" - def focalLength(self, missing=''): + def focal_length(self, missing=''): return "135" - def cameraMake(self, missing=''): + def camera_make(self, missing=''): return "Canon" - def cameraModel(self, missing=''): + def camera_model(self, missing=''): return "Canon EOS 5D" - def shortCameraModel(self, includeCharacters = '', missing=''): + def short_camera_model(self, includeCharacters = '', missing=''): return "5D" - def cameraSerial(self, missing=''): + def camera_serial(self, missing=''): return '730402168' - def shutterCount(self, missing=''): + def shutter_count(self, missing=''): return '387' - def ownerName(self, missing=''): + def owner_name(self, missing=''): return 'Photographer Name' - def dateTime(self, missing=''): + def date_time(self, missing=''): return datetime.datetime.now() def subSeconds(self, missing='00'): @@ -572,16 +411,16 @@ if __name__ == '__main__': 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.exposure_time(missing='missing ') + " sec" + print m.exposure_time(alternativeFormat=True, missing='missing ') + print m.focal_length('missing ') + "mm" + print m.camera_make() + print m.camera_model() + print m.short_camera_model() + print m.short_camera_model(includeCharacters = "\-") + print m.date_time() print m.orientation() - print 'Serial number:', m.cameraSerial() - print 'Shutter count:', m.shutterCount() - print 'Subseconds:', m.subSeconds() + print 'Serial number:', m.camera_serial() + print 'Shutter count:', m.shutter_count() + print 'Subseconds:', m.sub_seconds() diff --git a/rapid/videometadata.py b/rapid/metadatavideo.py index 77f6791..7b6bc6c 100755..100644 --- a/rapid/videometadata.py +++ b/rapid/metadatavideo.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: latin1 -*- -### Copyright (C) 2007-10 Damon Lynch <damonlynch@gmail.com> +### Copyright (C) 2007-11 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 @@ -25,39 +25,29 @@ import time import subprocess import tempfile +import multiprocessing +import logging +logger = multiprocessing.get_logger() + import gtk -import media import paths -from filmstrip import add_filmstrip + +import rpdfile try: - import kaa.metadata from hachoir_core.cmd_line import unicodeFilename from hachoir_parser import createParser from hachoir_metadata import extractMetadata except ImportError: DOWNLOAD_VIDEO = False -VIDEO_THUMBNAIL_FILE_EXTENSIONS = ['thm'] -VIDEO_FILE_EXTENSIONS = ['3gp', 'avi', 'm2t', 'mov', 'mp4', 'mpeg','mpg', 'mod', 'tod'] - - - if DOWNLOAD_VIDEO: - - - try: - subprocess.check_call(["ffmpegthumbnailer", "-h"], stdout=subprocess.PIPE) - ffmpeg = True - except: - ffmpeg = False - def version_info(): from hachoir_metadata.version import VERSION return VERSION - def get_video_THM_file(fullFileName): + def get_video_THM_file(full_filename): """ Checks to see if a thumbnail file (THM) is in the same directory as the file. Expects a full path to be part of the file name. @@ -66,8 +56,8 @@ if DOWNLOAD_VIDEO: """ f = None - name, ext = os.path.splitext(fullFileName) - for e in VIDEO_THUMBNAIL_FILE_EXTENSIONS: + name, ext = os.path.splitext(full_filename) + for e in rpdfile.VIDEO_THUMBNAIL_FILE_EXTENSIONS: if os.path.exists(name + '.' + e): f = name + '.' + e break @@ -76,7 +66,7 @@ if DOWNLOAD_VIDEO: break return f - + class VideoMetaData(): def __init__(self, filename): """ @@ -85,13 +75,19 @@ if DOWNLOAD_VIDEO: self.filename = filename self.u_filename = unicodeFilename(filename) - self.parser = createParser(self.u_filename, self.filename) - self.metadata = extractMetadata(self.parser) - + self.metadata = None - def _kaa_get(self, key, missing, stream=None): + def _kaa_get(self, key, missing, stream=None): if not hasattr(self, 'info'): - self.info = kaa.metadata.parse(self.filename) + try: + from kaa.metadata import parse + except ImportError: + msg = """The package Kaa metadata does not exist. +It is needed to access FPS and codec video file metadata.""" + logger.error(msg) + self.info = None + else: + self.info = parse(self.filename) if self.info: if stream != None: v = self.info['video'][stream][key] @@ -104,23 +100,30 @@ if DOWNLOAD_VIDEO: else: return missing + def _load_hachoir_metadata_parser(self): + self.parser = createParser(self.u_filename, self.filename) + self.metadata = extractMetadata(self.parser) + def _get(self, key, missing): + if self.metadata is None: + self._load_hachoir_metadata_parser() + try: v = self.metadata.get(key) except: v = missing return v - def dateTime(self, missing=''): + def date_time(self, missing=''): return self._get('creation_date', missing) - def timeStamp(self, missing=''): + def time_stamp(self, missing=''): """ Returns a float value representing the time stamp, if it exists """ - dt = self.dateTime(missing=None) + dt = self.date_time(missing=None) if dt: - # convert it to a timestamp (not optimal, but better than nothing!) + # convert it to a time stamp (not optimal, but better than nothing!) v = time.mktime(dt.timetuple()) else: v = missing @@ -152,7 +155,7 @@ if DOWNLOAD_VIDEO: else: return None - def framesPerSecond(self, stream=0, missing=''): + def frames_per_second(self, stream=0, missing=''): fps = self._kaa_get('fps', missing, stream) try: fps = '%.0f' % float(fps) @@ -163,38 +166,8 @@ if DOWNLOAD_VIDEO: def fourcc(self, stream=0, missing=''): return self._kaa_get('fourcc', missing, stream) - def getThumbnailData(self, size, tempWorkingDir): - """ - Returns a pixbuf of the video's thumbnail + - If it cannot be created, returns None - """ - thm = get_video_THM_file(self.filename) - if thm: - thumbnail = gtk.gdk.pixbuf_new_from_file(thm) - aspect = float(thumbnail.get_height()) / thumbnail.get_width() - thumbnail = thumbnail.scale_simple(size, int(aspect*size), gtk.gdk.INTERP_BILINEAR) - thumbnail = add_filmstrip(thumbnail) - else: - if ffmpeg: - try: - tmp = tempfile.NamedTemporaryFile(dir=tempWorkingDir, prefix="rpd-tmp") - tmp.close() - except: - return None - - thm = os.path.join(tempWorkingDir, tmp.name) - - try: - subprocess.check_call(['ffmpegthumbnailer', '-i', self.filename, '-t', '10', '-f', '-o', thm, '-s', str(size)]) - thumbnail = gtk.gdk.pixbuf_new_from_file_at_size(thm, size, size) - os.unlink(thm) - except: - thumbnail = None - else: - thumbnail = None - return thumbnail - class DummyMetaData(): """ Class which gives metadata values for an imaginary video. @@ -204,10 +177,10 @@ class DummyMetaData(): See VideoMetaData class for documentation of class methods. """ - def __init__(self): + def __init__(self, filename): pass - def dateTime(self, missing=''): + def date_time(self, missing=''): return datetime.datetime.now() def codec(self, stream=0, missing=''): @@ -222,7 +195,7 @@ class DummyMetaData(): def height(self, stream=0, missing=''): return '1080' - def framesPerSecond(self, stream=0, missing=''): + def frames_per_second(self, stream=0, missing=''): return '24' def fourcc(self, stream=0, missing=''): @@ -239,12 +212,12 @@ if __name__ == '__main__': else: m = VideoMetaData(sys.argv[1]) - dt = m.dateTime() + dt = m.date_time() if dt: print dt.strftime('%Y%m%d-%H:%M:%S') print "codec: %s" % m.codec() print "%s seconds" % m.length() print "%sx%s" % (m.width(), m.height()) - print "%s fps" % m.framesPerSecond() + print "%s fps" % m.frames_per_second() print "Fourcc: %s" % (m.fourcc()) diff --git a/rapid/preferencesdialog.py b/rapid/preferencesdialog.py new file mode 100644 index 0000000..368b064 --- /dev/null +++ b/rapid/preferencesdialog.py @@ -0,0 +1,1658 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007 - 2011 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 datetime + +import gtk + +import datetime +import multiprocessing +import logging +logger = multiprocessing.get_logger() + +import ValidatedEntry +import misc + +import config +import paths +import rpdfile +import higdefaults as hd +import metadataphoto +import metadatavideo +import tableplusminus as tpm + +import utilities + +import generatename as gn +from generatenameconfig import * +import problemnotification as pn + +from prefsrapid import format_pref_list_for_pretty_print, DownloadsTodayTracker + +from gettext import gettext as _ + +class PrefError(Exception): + """ base class """ + def unpackList(self, l): + """ + Make the preferences presentable to the user + """ + + 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:" + "\n %s" % self.unpackList(error) + +class PrefValueKeyComboError(PrefError): + def __init__(self, error): + self.msg = error + + +def check_pref_valid(pref_defn, prefs, modulo=3): + """ + Checks to see if prefs are valid according to definition. + + prefs is a list of preferences. + pref_defn 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 pref_defn, + else raises appropriate error. + """ + + if (len(prefs) % modulo <> 0) or not prefs: + raise PrefLengthError(prefs) + else: + for i in range(0, len(prefs), modulo): + _check_pref_valid(pref_defn, prefs[i:i+modulo]) + + return True + +def _check_pref_valid(pref_defn, prefs): + + key = prefs[0] + value = prefs[1] + + + if pref_defn.has_key(key): + + next_pref_defn = pref_defn[key] + + if value == None: + # value should never be None, at any time + raise PrefValueInvalidError((None, next_pref_defn)) + + if next_pref_defn and not value: + raise gn.PrefValueInvalidError((value, next_pref_defn)) + + if type(next_pref_defn) == type({}): + return _check_pref_valid(next_pref_defn, prefs[1:]) + else: + if type(next_pref_defn) == type([]): + result = value in next_pref_defn + if not result: + raise gn.PrefValueInvalidError((value, next_pref_defn)) + return True + elif not next_pref_defn: + return True + else: + result = next_pref_defn == value + if not result: + raise gn.PrefKeyValue((value, next_pref_defn)) + return True + else: + raise PrefKeyError((key, pref_defn[ORDER_KEY])) + + +def filter_subfolder_prefs(pref_list): + """ + Filters out extraneous preference choices + """ + prefs_changed = False + continue_check = True + while continue_check and pref_list: + continue_check = False + if pref_list[0] == SEPARATOR: + # subfolder preferences should not start with a / + pref_list = pref_list[3:] + prefs_changed = True + continue_check = True + elif pref_list[-3] == SEPARATOR: + # subfolder preferences should not end with a / + pref_list = pref_list[:-3] + continue_check = True + prefs_changed = True + else: + for i in range(0, len(pref_list) - 3, 3): + if pref_list[i] == SEPARATOR and pref_list[i+3] == SEPARATOR: + # subfolder preferences should not contain two /s side by side + continue_check = True + prefs_changed = True + # note we are messing with the contents of the pref list, + # must exit loop and try again + pref_list = pref_list[:i] + pref_list[i+3:] + break + + return (prefs_changed, pref_list) + +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) + # must name the combo box on pygtk used in Ubuntu 11.04, Fedora 15, etc. + self.set_name('GtkComboBox') + + 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 PreferenceWidgets: + + def __init__(self, default_row, default_prefs, pref_defn_L0, pref_list): + self.default_row = default_row + self.default_prefs = default_prefs + self.pref_defn_L0 = pref_defn_L0 + self.pref_list = pref_list + + def _create_combo(self, choices): + combobox = Comboi18n() + for text in choices: + combobox.append_text(text) + return combobox + + def get_default_row(self): + """ + returns a list of default widgets + """ + return self.get_widgets_based_on_user_selection(self.default_row) + + def _get_pref_widgets(self, pref_definition, 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 = pref_definition[ORDER_KEY][0] + + if not key in pref_definition: + raise gn.PrefKeyError((key, pref_definition.keys())) + + + list0 = pref_definition[ORDER_KEY] + + # the first widget will always be a combo box + widget0 = self._create_combo(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 in [SEPARATOR, JOB_CODE]: + widgets.append(None) + widgets.append(None) + return + else: + next_pref_definition = pref_definition[key] + if type(next_pref_definition) == type({}): + return self._get_pref_widgets(next_pref_definition, + prefs[1:], + widgets) + else: + if type(next_pref_definition) == type([]): + widget1 = self._create_combo(next_pref_definition) + if not value: + value = next_pref_definition[0] + try: + widget1.set_active(next_pref_definition.index(value)) + except: + raise gn.PrefValueInvalidError((value, next_pref_definition)) + + widgets.append(widget1) + else: + widgets.append(None) + + def _get_values_from_list(self): + for i in range(0, len(self.pref_list), 3): + yield (self.pref_list[i], self.pref_list[i+1], self.pref_list[i+2]) + + def get_widgets_based_on_prefs(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._get_values_from_list(): + prefs = [L0, L1, L2] + widgets = [] + self._get_pref_widgets(self.pref_defn_L0, prefs, widgets) + yield widgets + + + def get_widgets_based_on_user_selection(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._get_pref_widgets(self.pref_defn_L0, selection, widgets) + return widgets + + def check_prefs_for_validity(self): + """ + Checks preferences validity + """ + + return check_pref_valid(self.pref_defn_L0, self.pref_list) + +class PhotoNamePrefs(PreferenceWidgets): + def __init__(self, pref_list): + PreferenceWidgets.__init__(self, + default_row = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], + default_prefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], + pref_defn_L0 = DICT_IMAGE_RENAME_L0, + pref_list = pref_list) + +class VideoNamePrefs(PreferenceWidgets): + def __init__(self, pref_list): + PreferenceWidgets.__init__(self, + default_row = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], + default_prefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE], + pref_defn_L0 = DICT_VIDEO_RENAME_L0, + pref_list = pref_list) + + +class PhotoSubfolderPrefs(PreferenceWidgets): + def __init__(self, pref_list): + + PreferenceWidgets.__init__(self, + default_row = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]], + default_prefs = DEFAULT_SUBFOLDER_PREFS, + pref_defn_L0 = DICT_SUBFOLDER_L0, + pref_list = pref_list) + + def filter_preferences(self): + filtered, pref_list = filter_subfolder_prefs(self.pref_list) + if filtered: + self.pref_list = pref_list + + def check_prefs_for_validity(self): + """ + Checks subfolder preferences validity above and beyond image name checks. + + See parent method for full description. + + Subfolders have additional requirments to that of file names. + """ + v = PreferenceWidgets.check_prefs_for_validity(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.pref_list), 3): + L1s.append(self.pref_list[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 VideoSubfolderPrefs(PhotoSubfolderPrefs): + def __init__(self, pref_list): + PreferenceWidgets.__init__(self, + default_row = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[0]], + default_prefs = DEFAULT_VIDEO_SUBFOLDER_PREFS, + pref_defn_L0 = DICT_VIDEO_SUBFOLDER_L0, + pref_list = pref_list) + +class RemoveAllJobCodeDialog(gtk.Dialog): + def __init__(self, parent_window, post_choice_callback): + gtk.Dialog.__init__(self, _('Remove all Job Codes?'), None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, + gtk.STOCK_YES, gtk.RESPONSE_OK)) + + self.post_choice_callback = post_choice_callback + self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) + + prompt_hbox = gtk.HBox() + + icontheme = gtk.icon_theme_get_default() + icon = icontheme.load_icon('gtk-dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) + if icon: + image = gtk.Image() + image.set_from_pixbuf(icon) + prompt_hbox.pack_start(image, False, False, padding = 6) + + prompt_label = gtk.Label(_('Should all Job Codes be removed?')) + prompt_label.set_line_wrap(True) + prompt_hbox.pack_start(prompt_label, False, False, padding=6) + + self.vbox.pack_start(prompt_hbox, padding=6) + + self.set_border_width(6) + self.set_has_separator(False) + + self.set_default_response(gtk.RESPONSE_OK) + + + self.set_transient_for(parent_window) + self.show_all() + + + self.connect('response', self.on_response) + + def on_response(self, device_dialog, response): + user_selected = response == gtk.RESPONSE_OK + self.post_choice_callback(self, user_selected) + +class PhotoRenameTable(tpm.TablePlusMinus): + + def __init__(self, preferencesdialog, adjust_scroll_window): + + tpm.TablePlusMinus.__init__(self, 1, 3) + self.preferencesdialog = preferencesdialog + self.adjust_scroll_window = adjust_scroll_window + if not hasattr(self, "error_title"): + self.error_title = _("Error in Photo Rename preferences") + + self.table_type = self.error_title[len("Error in "):] + self.i = 0 + + if adjust_scroll_window: + self.scroll_bar = self.adjust_scroll_window.get_vscrollbar() + #this next line does not work on early versions of pygtk :( + self.scroll_bar.connect('visibility-notify-event', self.scrollbar_visibility_change) + self.connect("size-request", self.size_adjustment) + self.connect("add", self.size_adjustment) + self.connect("remove", self.size_adjustment) + + # get scrollbar thickness from parent app scrollbar - very hackish, but what to do?? + self.bump = 16# self.preferencesdialog.parentApp.image_scrolledwindow.get_hscrollbar().allocation.height + self.have_vertical_scrollbar = False + + + self.get_preferencesdialog_prefs() + self.setup_prefs_factory() + + try: + self.prefs_factory.check_prefs_for_validity() + + except (PrefValueInvalidError, PrefLengthError, + PrefValueKeyComboError, PrefKeyError), e: + + logger.error(self.error_title) + logger.error("Sorry, these preferences contain an error:") + logger.error(format_pref_list_for_pretty_print(self.prefs_factory.pref_list)) + + # the preferences were invalid + # reset them to their default + + self.pref_list = self.prefs_factory.default_prefs + self.setup_prefs_factory() + self.update_parentapp_prefs() + + msg = "%s.\n" % e + msg += "Resetting to default values." + logger.error(msg) + + + misc.run_dialog(self.error_title, msg, + preferencesdialog, + gtk.MESSAGE_ERROR) + + for row in self.prefs_factory.get_widgets_based_on_prefs(): + self.append(row) + + def update_preferences(self): + pref_list = [] + for row in self.pm_rows: + for col in range(self.pm_no_columns): + 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: + logger.critical("Program error: Unknown preference widget!") + value = '' + else: + value = '' + pref_list.append(value) + + self.pref_list = pref_list + self.update_parentapp_prefs() + self.prefs_factory.pref_list = pref_list + self.update_example() + + + def scrollbar_visibility_change(self, widget, event): + if event.state == gtk.gdk.VISIBILITY_UNOBSCURED: + self.have_vertical_scrollbar = True + self.adjust_scroll_window.set_size_request(self.adjust_scroll_window.allocation.width + self.bump, -1) + + + def size_adjustment(self, widget, arg2): + """ + Adjust scrolledwindow width in preferences dialog to reflect width of image rename table + + The algorithm is complicated by the need to take into account the presence of a vertical scrollbar, + which might be added as the user adds more rows + + The pygtk code behaves inconsistently depending on the pygtk version + """ + + if self.adjust_scroll_window: + self.have_vertical_scrollbar = self.scroll_bar.allocation.width > 1 or self.have_vertical_scrollbar + if not self.have_vertical_scrollbar: + if self.allocation.width > self.adjust_scroll_window.allocation.width: + self.adjust_scroll_window.set_size_request(self.allocation.width, -1) + else: + if self.allocation.width > self.adjust_scroll_window.allocation.width - self.bump: + self.adjust_scroll_window.set_size_request(self.allocation.width + self.bump, -1) + self.bump = 0 + + def get_preferencesdialog_prefs(self): + self.pref_list = self.preferencesdialog.prefs.image_rename + + + def setup_prefs_factory(self): + self.prefs_factory = PhotoNamePrefs(self.pref_list) + + def update_parentapp_prefs(self): + self.preferencesdialog.prefs.image_rename = self.pref_list + + def update_example_job_code(self): + job_code = self.preferencesdialog.prefs.get_sample_job_code() + if not job_code: + job_code = _('Job code') + #~ self.prefs_factory.setJobCode(job_code) + + def update_example(self): + self.preferencesdialog.update_photo_rename_example() + + def get_default_row(self): + return self.prefs_factory.get_default_row() + + def on_combobox_changed(self, widget, row_position): + + for col in range(self.pm_no_columns): + if self.pm_rows[row_position][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[row_position][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_no_columns): + selection.append('') + + if col <> (self.pm_no_columns - 1): + widgets = self.prefs_factory.get_widgets_based_on_user_selection(selection) + + for i in range(col + 1, self.pm_no_columns): + old_widget = self.pm_rows[row_position][i] + if old_widget: + self.remove(old_widget) + if old_widget in self.pm_callbacks: + del self.pm_callbacks[old_widget] + new_widget = widgets[i] + self.pm_rows[row_position][i] = new_widget + if new_widget: + self._create_callback(new_widget, row_position) + self.attach(new_widget, i, i+1, row_position, row_position + 1) + new_widget.show() + self.update_preferences() + + + def on_entry_changed(self, widget, row_position): + self.update_preferences() + + def on_row_added(self, row_position): + """ + Update preferences, as a row has been added + """ + self.update_preferences() + + # if this was the last row or 2nd to last row, and another has just been added, move vertical scrollbar down + if row_position in range(self.pm_no_rows - 3, self.pm_no_rows - 2): + adjustment = self.preferencesdialog.rename_scrolledwindow.get_vadjustment() + adjustment.set_value(adjustment.upper) + + + def on_row_deleted(self, row_position): + """ + Update preferences, as a row has been deleted + """ + self.update_preferences() + +class VideoRenameTable(PhotoRenameTable): + def __init__(self, preferencesdialog, adjust_scroll_window): + self.error_title = _("Error in Video Rename preferences") + PhotoRenameTable.__init__(self, preferencesdialog, adjust_scroll_window) + + def get_preferencesdialog_prefs(self): + self.pref_list = self.preferencesdialog.prefs.video_rename + + def setup_prefs_factory(self): + self.prefs_factory = VideoNamePrefs(self.pref_list) + + def update_parentapp_prefs(self): + self.preferencesdialog.prefs.video_rename = self.pref_list + + def update_example(self): + self.preferencesdialog.update_video_rename_example() + +class SubfolderTable(PhotoRenameTable): + """ + Table to display photo download subfolder preferences as part of preferences + dialog window. + """ + def __init__(self, preferencesdialog, adjust_scroll_window): + self.error_title = _("Error in Photo Download Subfolders preferences") + PhotoRenameTable.__init__(self, preferencesdialog, adjust_scroll_window) + + def get_preferencesdialog_prefs(self): + self.pref_list = self.preferencesdialog.prefs.subfolder + + def setup_prefs_factory(self): + self.prefs_factory = PhotoSubfolderPrefs(self.pref_list) + + def update_parentapp_prefs(self): + self.preferencesdialog.prefs.subfolder = self.pref_list + + def update_example(self): + self.preferencesdialog.update_photo_download_folder_example() + +class VideoSubfolderTable(PhotoRenameTable): + def __init__(self, preferencesdialog, adjust_scroll_window): + self.error_title = _("Error in Video Download Subfolders preferences") + PhotoRenameTable.__init__(self, preferencesdialog, adjust_scroll_window) + + def get_preferencesdialog_prefs(self): + self.pref_list = self.preferencesdialog.prefs.video_subfolder + + def setup_prefs_factory(self): + self.prefs_factory = VideoSubfolderPrefs(self.pref_list) + + def update_parentapp_prefs(self): + self.preferencesdialog.prefs.video_subfolder = self.pref_list + + def update_example(self): + self.preferencesdialog.update_video_download_folder_example() + +class RemoveAllJobCodeDialog(gtk.Dialog): + def __init__(self, parent_window, post_choice_callback): + gtk.Dialog.__init__(self, _('Remove all Job Codes?'), None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, + gtk.STOCK_YES, gtk.RESPONSE_OK)) + + self.post_choice_callback = post_choice_callback + self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) + + prompt_hbox = gtk.HBox() + + icontheme = gtk.icon_theme_get_default() + icon = icontheme.load_icon('gtk-dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) + if icon: + image = gtk.Image() + image.set_from_pixbuf(icon) + prompt_hbox.pack_start(image, False, False, padding = 6) + + prompt_label = gtk.Label(_('Should all Job Codes be removed?')) + prompt_label.set_line_wrap(True) + prompt_hbox.pack_start(prompt_label, False, False, padding=6) + + self.vbox.pack_start(prompt_hbox, padding=6) + + self.set_border_width(6) + self.set_has_separator(False) + + self.set_default_response(gtk.RESPONSE_OK) + + self.set_transient_for(parent_window) + self.show_all() + + self.connect('response', self.on_response) + + def on_response(self, device_dialog, response): + user_selected = response == gtk.RESPONSE_OK + self.post_choice_callback(self, user_selected) + +class JobCodeDialog(gtk.Dialog): + """ Dialog prompting for a job code""" + + def __init__(self, parent_window, job_codes, default_job_code, post_job_code_entry_callback, entry_only): + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode + gtk.Dialog.__init__(self, _('Enter a Job Code'), None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OK, gtk.RESPONSE_OK)) + + + self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) + self.post_job_code_entry_callback = post_job_code_entry_callback + + self.combobox = gtk.combo_box_entry_new_text() + for text in job_codes: + self.combobox.append_text(text) + + self.job_code_hbox = gtk.HBox(homogeneous = False) + + if len(job_codes) and not entry_only: + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode + task_label = gtk.Label(_('Enter a new Job Code, or select a previous one')) + else: + # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode + task_label = gtk.Label(_('Enter a new Job Code')) + task_label.set_line_wrap(True) + task_hbox = gtk.HBox() + task_hbox.pack_start(task_label, False, False, padding=6) + + label = gtk.Label(_('Job Code:')) + self.job_code_hbox.pack_start(label, False, False, padding=6) + self.job_code_hbox.pack_start(self.combobox, True, True, padding=6) + + self.set_border_width(6) + self.set_has_separator(False) + + # make entry box have entry completion + self.entry = self.combobox.child + + completion = gtk.EntryCompletion() + completion.set_match_func(self.match_func) + completion.connect("match-selected", + self.on_completion_match) + completion.set_model(self.combobox.get_model()) + completion.set_text_column(0) + self.entry.set_completion(completion) + + # when user hits enter, close the dialog window + self.set_default_response(gtk.RESPONSE_OK) + self.entry.set_activates_default(True) + + if default_job_code: + self.entry.set_text(default_job_code) + + self.vbox.pack_start(task_hbox, False, False, padding = 6) + self.vbox.pack_start(self.job_code_hbox, False, False, padding=12) + + self.set_transient_for(parent_window) + self.show_all() + self.connect('response', self.on_job_code_resp) + + def match_func(self, completion, key, iter): + model = completion.get_model() + return model[iter][0].lower().startswith(self.entry.get_text().lower()) + + def on_completion_match(self, completion, model, iter): + self.entry.set_text(model[iter][0]) + self.entry.set_position(-1) + + def get_job_code(self): + return self.combobox.child.get_text() + + def on_job_code_resp(self, jc_dialog, response): + user_chose_code = False + if response == gtk.RESPONSE_OK: + user_chose_code = True + logger.debug("Job Code entered") + else: + logger.debug("Job Code not entered") + self.post_job_code_entry_callback(self, user_chose_code, self.get_job_code()) + + +class PreferencesDialog(): + """ + Dialog window to show Rapid Photo Downloader preferences. + + Is tightly integrated into main Rapid Photo Downloader window, i.e. + directly access members in class RapidApp. + """ + + def __init__(self, rapidapp): + + self.builder = gtk.Builder() + self.builder.add_from_file(paths.share_dir("glade3/prefs.ui")) + self.builder.connect_signals(self) + + self.dialog = self.preferencesdialog + self.widget = self.dialog + self.dialog.set_transient_for(rapidapp.rapidapp) + self.prefs = rapidapp.prefs + + rapidapp.preferences_dialog_displayed = True + + self.pref_dialog_startup = True + + self.rapidapp = rapidapp + + self._setup_tab_selector() + + self._setup_control_spacing() + + if metadatavideo.DOWNLOAD_VIDEO: + self.file_types = _("photos and videos") + else: + self.file_types = _("photos") + + self._setup_sample_names() + + # setup tabs + self._setup_photo_download_folder_tab() + self._setup_image_rename_tab() + self._setup_video_download_folder_tab() + self._setup_video_rename_tab() + self._setup_rename_options_tab() + self._setup_job_code_tab() + self._setup_device_tab() + self._setup_backup_tab() + self._setup_miscellaneous_tab() + self._setup_error_tab() + + if not metadatavideo.DOWNLOAD_VIDEO: + self.disable_video_controls() + + self.dialog.realize() + + #set the width of the left column for selecting values + #note: this must be called after self.dialog.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 photo 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.dialog.show() + + self.pref_dialog_startup = False + + def __getattr__(self, key): + """Allow builder widgets to be accessed as self.widgetname + """ + widget = self.builder.get_object(key) + if widget: # cache lookups + setattr(self, key, widget) + return widget + raise AttributeError(key) + + def on_preferencesdialog_destroy(self, widget): + """ Delete variables from memory that cause a file descriptor to be created on a mounted media""" + logger.debug("Preference window closing") + + def _setup_tab_selector(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.update_photo_download_folder_example() + + def on_video_download_folder_filechooser_button_selection_changed(self, widget): + self.prefs.video_download_folder = widget.get_current_folder() + self.update_video_download_folder_example() + + def on_backup_folder_filechooser_button_selection_changed(self, widget): + self.prefs.backup_location = widget.get_current_folder() + self.update_backup_example() + + def on_device_location_filechooser_button_selection_changed(self, widget): + self.prefs.device_location = widget.get_current_folder() + + def _setup_sample_names(self, use_dummy_data = False): + """ + If use_dummy_data is True, then samples will not attempt to get + data from actual download files + """ + job_code = self.prefs.most_recent_job_code() + if job_code is None: + job_code = _("Job Code") + self.downloads_today_tracker = DownloadsTodayTracker( + day_start = self.prefs.day_start, + downloads_today = self.prefs.downloads_today[1], + downloads_today_date = self.prefs.downloads_today[0]) + self.sequences = gn.Sequences(self.downloads_today_tracker, + self.prefs.stored_sequence_no) + + # get example photo and video data + if use_dummy_data: + self.sample_photo = None + else: + self.sample_photo = self.rapidapp.thumbnails.get_sample_file(rpdfile.FILE_TYPE_PHOTO) + if self.sample_photo is not None: + # try to load metadata from the file returned + # if it fails, give up with this sample file + if not self.sample_photo.load_metadata(): + self.sample_photo = None + else: + self.sample_photo.sequences = self.sequences + self.sample_photo.download_start_time = datetime.datetime.now() + + if self.sample_photo is None: + self.sample_photo = rpdfile.SamplePhoto(sequences=self.sequences) + + self.sample_photo.job_code = job_code + + self.sample_video = None + if metadatavideo.DOWNLOAD_VIDEO: + if not use_dummy_data: + self.sample_video = self.rapidapp.thumbnails.get_sample_file(rpdfile.FILE_TYPE_VIDEO) + if self.sample_video is not None: + self.sample_video.load_metadata() + self.sample_video.sequences = self.sequences + self.sample_video.download_start_time = datetime.datetime.now() + if self.sample_video is None: + self.sample_video = rpdfile.SampleVideo(sequences=self.sequences) + self.sample_video.job_code = job_code + + + + def _setup_control_spacing(self): + """ + set spacing of some but not all controls + """ + + self._setup_table_spacing(self.download_folder_table) + self._setup_table_spacing(self.video_download_folder_table) + self.download_folder_table.set_row_spacing(2, + hd.VERTICAL_CONTROL_SPACE) + self.video_download_folder_table.set_row_spacing(2, + hd.VERTICAL_CONTROL_SPACE) + self._setup_table_spacing(self.rename_example_table) + self._setup_table_spacing(self.video_rename_example_table) + self.devices_table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) + self.automation_table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) + + self._setup_table_spacing(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._setup_table_spacing(self.compatibility_table) + self.compatibility_table.set_row_spacing(0, + hd.VERTICAL_CONTROL_LABEL_SPACE) + self._setup_table_spacing(self.error_table) + + + def _setup_table_spacing(self, table): + table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE) + table.set_col_spacing(1, hd.CONTROL_LABEL_SPACE) + + def _setup_subfolder_table(self): + self.subfolder_table = SubfolderTable(self, None) + self.subfolder_vbox.pack_start(self.subfolder_table) + self.subfolder_table.show_all() + + def _setup_video_subfolder_table(self): + self.video_subfolder_table = VideoSubfolderTable(self, None) + self.video_subfolder_vbox.pack_start(self.video_subfolder_table) + self.video_subfolder_table.show_all() + + def _setup_photo_download_folder_tab(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._setup_subfolder_table() + self.update_photo_download_folder_example() + + def _setup_video_download_folder_tab(self): + self.video_download_folder_filechooser_button = gtk.FileChooserButton( + _("Select a folder to download videos to")) + self.video_download_folder_filechooser_button.set_current_folder( + self.prefs.video_download_folder) + self.video_download_folder_filechooser_button.set_action( + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + self.video_download_folder_filechooser_button.connect("selection-changed", + self.on_video_download_folder_filechooser_button_selection_changed) + + self.video_download_folder_table.attach( + self.video_download_folder_filechooser_button, + 2, 3, 2, 3, yoptions = gtk.SHRINK) + self.video_download_folder_filechooser_button.show() + self._setup_video_subfolder_table() + self.update_video_download_folder_example() + + def _setup_image_rename_tab(self): + + self.rename_table = PhotoRenameTable(self, self.rename_scrolledwindow) + self.rename_table_vbox.pack_start(self.rename_table) + self.rename_table.show_all() + self._setup_photo_original_name() + self.update_photo_rename_example() + + def _setup_photo_original_name(self): + self.original_name_label.set_markup("<i>%s</i>" % self.sample_photo.display_name) + + def _setup_video_rename_tab(self): + + self.video_rename_table = VideoRenameTable(self, self.video_rename_scrolledwindow) + self.video_rename_table_vbox.pack_start(self.video_rename_table) + self.video_rename_table.show_all() + self._setup_video_original_name() + self.update_video_rename_example() + + def _setup_video_original_name(self): + if self.sample_video is not None: + self.video_original_name_label.set_markup("<i>%s</i>" % self.sample_video.display_name) + else: + self.video_original_name_label.set_markup("") + + def _setup_rename_options_tab(self): + + # sequence numbers + 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.rapidapp.downloads_today_tracker.get_and_maybe_reset_downloads_today() + 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.rapidapp.downloads_today_tracker.get_day_start() + self.hour_spinbutton.set_value(float(hour)) + self.minute_spinbutton.set_value(float(minute)) + + self.synchronize_raw_jpg_checkbutton.set_active( + self.prefs.synchronize_raw_jpg) + + #compatibility + self.strip_characters_checkbutton.set_active( + self.prefs.strip_characters) + + def _setup_job_code_tab(self): + self.job_code_liststore = gtk.ListStore(str) + column = gtk.TreeViewColumn() + rentext = gtk.CellRendererText() + rentext.connect('edited', self.on_job_code_edited) + rentext .set_property('editable', True) + + column.pack_start(rentext, expand=0) + column.set_attributes(rentext, text=0) + self.job_code_treeview_column = column + self.job_code_treeview.append_column(column) + self.job_code_treeview.props.model = self.job_code_liststore + for code in self.prefs.job_codes: + self.job_code_liststore.append((code, )) + + # set multiple selections + self.job_code_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) + + self.remove_all_job_code_button.set_image(gtk.image_new_from_stock( + gtk.STOCK_CLEAR, + gtk.ICON_SIZE_BUTTON)) + def _setup_device_tab(self): + + self.device_location_filechooser_button = gtk.FileChooserButton( + _("Select a folder containing %(file_types)s") % {'file_types':self.file_types}) + 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.update_device_controls() + + + def _setup_backup_tab(self): + self.backup_folder_filechooser_button = gtk.FileChooserButton( + _("Select a folder in which to backup %(file_types)s") % {'file_types':self.file_types}) + 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, 8, 9, yoptions = gtk.SHRINK) + self.backup_folder_filechooser_button.show() + self.backup_identifier_entry.set_text(self.prefs.backup_identifier) + self.video_backup_identifier_entry.set_text(self.prefs.video_backup_identifier) + + #setup controls for manipulating sensitivity + self._backup_controls0 = [self.auto_detect_backup_checkbutton] + self._backup_controls1 = [self.backup_identifier_explanation_label, + self.backup_identifier_label, + self.backup_identifier_entry, + self.example_backup_path_label, + self.backup_example_label,] + self._backup_controls2 = [self.backup_location_label, + self.backup_folder_filechooser_button, + self.backup_location_explanation_label] + self._backup_controls = self._backup_controls0 + self._backup_controls1 + \ + self._backup_controls2 + + self._backup_video_controls = [self.video_backup_identifier_label, + self.video_backup_identifier_entry] + + #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.update_backup_controls() + self.update_backup_example() + + def _setup_miscellaneous_tab(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) + self.auto_exit_force_checkbutton.set_active( + self.prefs.auto_exit_force) + self.auto_delete_checkbutton.set_active( + self.prefs.auto_delete) + self.generate_thumbnails_checkbutton.set_active( + self.prefs.generate_thumbnails) + + self.update_misc_controls() + + + def _setup_error_tab(self): + 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_duplicate_overwrite: + self.backup_duplicate_overwrite_radiobutton.set_active(True) + else: + self.backup_duplicate_skip_radiobutton.set_active(True) + + + def update_example_file_name(self, display_table, rename_table, sample_rpd_file, generator, example_label): + if hasattr(self, display_table) and sample_rpd_file is not None: + sample_rpd_file.download_folder = self.prefs.get_download_folder_for_file_type(sample_rpd_file.file_type) + sample_rpd_file.strip_characters = self.prefs.strip_characters + sample_rpd_file.initialize_problem() + name = generator.generate_name(sample_rpd_file) + else: + name = '' + + # since this is markup, escape it + text = "<i>%s</i>" % utilities.escape(name) + + if sample_rpd_file is not None: + if sample_rpd_file.has_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 metadata to fully generate the name. Please use other renaming options.</i>") + + example_label.set_markup(text) + + def update_photo_rename_example(self): + """ + Displays example image name to the user + """ + generator = gn.PhotoName(self.prefs.image_rename) + self.update_example_file_name('rename_table', self.rename_table, + self.sample_photo, generator, + self.new_name_label) + + + def update_video_rename_example(self): + """ + Displays example video name to the user + """ + if self.sample_video is not None: + generator = gn.VideoName(self.prefs.video_rename) + else: + generator = None + self.update_example_file_name('video_rename_table', + self.video_rename_table, + self.sample_video, generator, + self.video_new_name_label) + + def update_download_folder_example(self, display_table, subfolder_table, + download_folder, sample_rpd_file, + generator, + example_download_path_label, + subfolder_warning_label): + """ + Displays example subfolder name(s) to the user + """ + + if hasattr(self, display_table) and sample_rpd_file is not None: + #~ subfolder_table.update_example_job_code() + sample_rpd_file.strip_characters = self.prefs.strip_characters + sample_rpd_file.initialize_problem() + path = generator.generate_name(sample_rpd_file) + else: + path = '' + + text = os.path.join(download_folder, path) + # since this is markup, escape it + path = utilities.escape(text) + + warning = "" + if sample_rpd_file is not None: + if sample_rpd_file.has_problem(): + warning = _("<i><b>Warning:</b> There is insufficient metadata to fully generate subfolders. Please use other subfolder naming options.</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 + example_download_path_label.set_markup(_("<i>Example: %s</i>") % text) + subfolder_warning_label.set_markup(warning) + + def update_photo_download_folder_example(self): + if hasattr(self, 'subfolder_table'): + generator = gn.PhotoSubfolder(self.prefs.subfolder) + self.update_download_folder_example('subfolder_table', + self.subfolder_table, self.prefs.download_folder, + self.sample_photo, generator, + self.example_photo_download_path_label, + self.photo_subfolder_warning_label) + + def update_video_download_folder_example(self): + if hasattr(self, 'video_subfolder_table'): + if self.sample_video is not None: + generator = gn.VideoSubfolder(self.prefs.video_subfolder) + else: + generator = None + self.update_download_folder_example('video_subfolder_table', + self.video_subfolder_table, + self.prefs.video_download_folder, + self.sample_video, generator, + self.example_video_download_path_label, + self.video_subfolder_warning_label) + + def on_hour_spinbutton_value_changed(self, spinbutton): + hour = spinbutton.get_value_as_int() + minute = self.minute_spinbutton.get_value_as_int() + self.rapidapp.downloads_today_tracker.set_day_start(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.rapidapp.downloads_today_tracker.set_day_start(hour, minute) + self.on_downloads_today_entry_changed(self.downloads_today_entry) + + def on_downloads_today_entry_changed(self, entry): + # do not update value if a download is occurring - it will mess it up! + if self.rapidapp.download_is_occurring(): + logger.info("Downloads today value not updated, as a download is currently occurring") + else: + v = entry.get_text() + try: + v = int(v) + except: + v = 0 + if v < 0: + v = 0 + self.rapidapp.downloads_today_tracker.reset_downloads_today(v) + self.rapidapp.refresh_downloads_today = True + self.update_photo_rename_example() + + def on_stored_number_entry_changed(self, entry): + # do not update value if a download is occurring - it will mess it up! + if self.rapidapp.download_is_occurring(): + logger.info("Stored number value not updated, as a download is currently occurring") + else: + 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 + self.update_photo_rename_example() + + def _update_subfolder_pref_on_error(self, new_pref_list): + self.prefs.subfolder = new_pref_list + + def _update_video_subfolder_pref_on_error(self, new_pref_list): + self.prefs.video_subfolder = new_pref_list + + + def check_subfolder_values_valid_on_exit(self, users_pref_list, update_pref_function, filetype, default_pref_list): + """ + Checks that the user has not entered in any inappropriate values + + If they have, filters out bad values and warns the user + """ + filtered, pref_list = filter_subfolder_prefs(users_pref_list) + if filtered: + logger.info("The %(filetype)s subfolder preferences had some unnecessary values removed.", {'filetype': filetype}) + if pref_list: + update_pref_function(pref_list) + else: + #Preferences list is now empty + msg = _("The %(filetype)s subfolder preferences entered are invalid and cannot be used.\nThey will be reset to their default values.") % {'filetype': filetype} + sys.stderr.write(msg + "\n") + misc.run_dialog(PROGRAM_NAME, msg) + update_pref_function(self.prefs.get_default(default_pref_list)) + + def on_preferencesdialog_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") + self.prefs.video_backup_identifier = self.video_backup_identifier_entry.get_property("text") + + #check subfolder preferences for bad values + self.check_subfolder_values_valid_on_exit(self.prefs.subfolder, self._update_subfolder_pref_on_error, _("photo"), "subfolder") + self.check_subfolder_values_valid_on_exit(self.prefs.video_subfolder, self._update_video_subfolder_pref_on_error, _("video"), "video_subfolder") + + self.dialog.destroy() + self.rapidapp.preferences_dialog_displayed = False + self.rapidapp.post_preference_change() + + + + + def on_add_job_code_button_clicked(self, button): + j = JobCodeDialog(parent_window = self.dialog, + job_codes = self.prefs.job_codes, + default_job_code = None, + post_job_code_entry_callback=self.add_job_code, + entry_only = True) + + def add_job_code(self, dialog, user_chose_code, job_code): + dialog.destroy() + if user_chose_code: + if job_code and job_code not in self.prefs.job_codes: + self.job_code_liststore.prepend((job_code, )) + self.update_job_codes() + selection = self.job_code_treeview.get_selection() + selection.unselect_all() + selection.select_path((0, )) + #scroll to the top + adjustment = self.job_code_scrolledwindow.get_vadjustment() + adjustment.set_value(adjustment.lower) + + def on_remove_job_code_button_clicked(self, button): + """ remove selected job codes (can be multiple selection)""" + selection = self.job_code_treeview.get_selection() + model, selected = selection.get_selected_rows() + iters = [model.get_iter(path) for path in selected] + # only delete if a jobe code is selected + if iters: + no = len(iters) + path = None + for i in range(0, no): + iter = iters[i] + if i == no - 1: + path = model.get_path(iter) + model.remove(iter) + + # now that we removed the selection, play nice with + # the user and select the next item + selection.select_path(path) + + # if there was no selection that meant the user + # removed the last entry, so we try to select the + # last item + if not selection.path_is_selected(path): + row = path[0]-1 + # test case for empty lists + if row >= 0: + selection.select_path((row,)) + + self.update_job_codes() + self.update_photo_rename_example() + self.update_video_rename_example() + self.update_photo_download_folder_example() + self.update_video_download_folder_example() + + def on_remove_all_job_code_button_clicked(self, button): + j = RemoveAllJobCodeDialog(self.dialog, self.remove_all_job_code) + + def remove_all_job_code(self, dialog, user_selected): + dialog.destroy() + if user_selected: + self.job_code_liststore.clear() + self.update_job_codes() + self.update_photo_rename_example() + self.update_video_rename_example() + self.update_photo_download_folder_example() + self.update_video_download_folder_example() + + def on_job_code_edited(self, widget, path, new_text): + iter = self.job_code_liststore.get_iter(path) + self.job_code_liststore.set_value(iter, 0, new_text) + self.update_job_codes() + self.update_photo_rename_example() + self.update_video_rename_example() + self.update_photo_download_folder_example() + self.update_video_download_folder_example() + + def update_job_codes(self): + """ update preferences with list of job codes""" + job_codes = [] + for row in self.job_code_liststore: + job_codes.append(row[0]) + self.prefs.job_codes = job_codes + + 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_delete_checkbutton_toggled(self, checkbutton): + self.prefs.auto_delete = checkbutton.get_active() + + def on_auto_exit_checkbutton_toggled(self, checkbutton): + active = checkbutton.get_active() + self.prefs.auto_exit = active + if not active: + self.prefs.auto_exit_force = False + self.auto_exit_force_checkbutton.set_active(False) + self.update_misc_controls() + + def on_auto_exit_force_checkbutton_toggled(self, checkbutton): + self.prefs.auto_exit_force = checkbutton.get_active() + + def on_autodetect_device_checkbutton_toggled(self, checkbutton): + self.prefs.device_autodetection = checkbutton.get_active() + self.update_device_controls() + + def on_autodetect_psd_checkbutton_toggled(self, checkbutton): + self.prefs.device_autodetection_psd = checkbutton.get_active() + + def on_generate_thumbnails_checkbutton_toggled(self, checkbutton): + self.prefs.generate_thumbnails = 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_treeview_cursor_changed(self, tree): + path, column = tree.get_cursor() + self.notebook.set_current_page(path[0]) + + def on_synchronize_raw_jpg_checkbutton_toggled(self, check_button): + self.prefs.synchronize_raw_jpg = check_button.get_active() + + def on_strip_characters_checkbutton_toggled(self, check_button): + self.prefs.strip_characters = check_button.get_active() + self.update_photo_rename_example() + self.update_photo_download_folder_example() + self.update_video_download_folder_example() + + 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 update_device_controls(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) + + if not self.pref_dialog_startup: + logger.debug("Resetting sample file photo and video files") + self._setup_sample_names(use_dummy_data = True) + self._setup_photo_original_name() + self.update_photo_download_folder_example() + self.update_photo_rename_example() + self.update_video_download_folder_example() + self._setup_video_original_name() + self.update_video_rename_example() + + def update_misc_controls(self): + """ + Sets sensitivity of miscillaneous controls + """ + + self.auto_exit_force_checkbutton.set_sensitive(self.prefs.auto_exit) + + + def update_backup_controls(self): + """ + Sets sensitivity of backup related widgets + """ + + if not self.backup_checkbutton.get_active(): + for c in self._backup_controls + self._backup_video_controls: + c.set_sensitive(False) + + else: + for c in self._backup_controls0: + c.set_sensitive(True) + self.update_backup_controls_auto() + + def update_backup_controls_auto(self): + """ + Sets sensitivity of subset of backup related widgets + """ + + if self.auto_detect_backup_checkbutton.get_active(): + for c in self._backup_controls1: + c.set_sensitive(True) + for c in self._backup_controls2: + c.set_sensitive(False) + for c in self._backup_video_controls: + c.set_sensitive(False) + if metadatavideo.DOWNLOAD_VIDEO: + for c in self._backup_video_controls: + c.set_sensitive(True) + else: + for c in self._backup_controls1: + c.set_sensitive(False) + for c in self._backup_controls2: + c.set_sensitive(True) + if metadatavideo.DOWNLOAD_VIDEO: + for c in self._backup_video_controls: + c.set_sensitive(False) + + def disable_video_controls(self): + """ + Disables video preferences if video downloading is disabled + (probably because the appropriate libraries to enable + video metadata extraction are not installed) + """ + controls = [self.example_video_filename_label, + self.original_video_filename_label, + self.new_video_filename_label, + self.video_new_name_label, + self.video_original_name_label, + self.video_rename_scrolledwindow, + self.video_folders_hbox, + self.video_backup_identifier_label, + self.video_backup_identifier_entry + ] + for c in controls: + c.set_sensitive(False) + + self.videos_cannot_be_downloaded_label.show() + self.folder_videos_cannot_be_downloaded_label.show() + self.folder_videos_cannot_be_downloaded_hbox.show() + + def on_auto_detect_backup_checkbutton_toggled(self, widget): + self.prefs.backup_device_autodetection = widget.get_active() + self.update_backup_controls_auto() + + def on_backup_checkbutton_toggled(self, widget): + self.prefs.backup_images = self.backup_checkbutton.get_active() + self.update_backup_controls() + + def on_backup_identifier_entry_changed(self, widget): + self.update_backup_example() + #~ self.prefs. + + def on_video_backup_identifier_entry_changed(self, widget): + self.update_backup_example() + + def on_backup_scan_folder_on_entry_changed(self, widget): + self.update_backup_example() + + def update_backup_example(self): + # Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this. + drive1 = 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. + drive2 = os.path.join(config.MEDIA_LOCATION, _("externaldrive2")) + + path = os.path.join(drive1, self.backup_identifier_entry.get_text()) + path2 = os.path.join(drive2, self.backup_identifier_entry.get_text()) + path3 = os.path.join(drive2, self.video_backup_identifier_entry.get_text()) + path = utilities.escape(path) + path2 = utilities.escape(path2) + path3 = utilities.escape(path3) + if metadatavideo.DOWNLOAD_VIDEO: + example = "<i>%s</i>\n<i>%s</i>\n<i>%s</i>" % (path, path2, path3) + else: + example = "<i>%s</i>\n<i>%s</i>" % (path, path2) + self.example_backup_path_label.set_markup(example) diff --git a/rapid/prefsrapid.py b/rapid/prefsrapid.py new file mode 100644 index 0000000..f13530f --- /dev/null +++ b/rapid/prefsrapid.py @@ -0,0 +1,416 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007, 2008, 2009, 2010, 2011 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 subprocess, os, datetime + +import prefs + +import preferencesdialog as pd +from generatenameconfig import * +import rpdfile + +import utilities +import config +__version__ = config.version + +import multiprocessing +import logging +logger = multiprocessing.get_logger() + +from gettext import gettext as _ + +def _get_default_location_legacy(options, ignore_missing_dir=False): + if ignore_missing_dir: + return utilities.get_full_path(options[0]) + for default in options: + path = utilities.get_full_path(default) + if os.path.isdir(path): + return path + return utilities.get_full_path('') + +def _get_default_location_XDG(dir_type): + proc = subprocess.Popen(['xdg-user-dir', dir_type], stdout=subprocess.PIPE) + output = proc.communicate()[0].strip() + return output + +def get_default_photo_location(ignore_missing_dir=False): + try: + return _get_default_location_XDG('PICTURES') + except: + return _get_default_location_legacy(config.DEFAULT_PHOTO_LOCATIONS, ignore_missing_dir) + +def get_default_video_location(ignore_missing_dir=False): + try: + return _get_default_location_XDG('VIDEOS') + except: + return _get_default_location_legacy(config.DEFAULT_VIDEO_LOCATIONS, ignore_missing_dir) + +def get_default_backup_photo_identifier(): + return os.path.split(get_default_photo_location(ignore_missing_dir = True))[1] + +def get_default_backup_video_identifier(): + return os.path.split(get_default_video_location(ignore_missing_dir = True))[1] + +def today(): + return datetime.date.today().strftime('%Y-%m-%d') + +class RapidPreferences(prefs.Preferences): + + defaults = { + "program_version": prefs.Value(prefs.STRING, ""), + "download_folder": prefs.Value(prefs.STRING, + get_default_photo_location()), + "video_download_folder": prefs.Value(prefs.STRING, + get_default_video_location()), + "subfolder": prefs.ListValue(prefs.STRING_LIST, DEFAULT_SUBFOLDER_PREFS), + "video_subfolder": prefs.ListValue(prefs.STRING_LIST, DEFAULT_VIDEO_SUBFOLDER_PREFS), + "image_rename": prefs.ListValue(prefs.STRING_LIST, [FILENAME, + NAME_EXTENSION, + ORIGINAL_CASE]), + "video_rename": prefs.ListValue(prefs.STRING_LIST, [FILENAME, + NAME_EXTENSION, + 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), + "device_whitelist": prefs.ListValue(prefs.STRING_LIST, ['']), + "device_blacklist": prefs.ListValue(prefs.STRING_LIST, ['']), + "backup_images": prefs.Value(prefs.BOOL, False), + "backup_device_autodetection": prefs.Value(prefs.BOOL, True), + "backup_identifier": prefs.Value(prefs.STRING, + get_default_backup_photo_identifier()), + "video_backup_identifier": prefs.Value(prefs.STRING, + get_default_backup_video_identifier()), + "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), + "auto_exit_force": prefs.Value(prefs.BOOL, False), + "auto_delete": prefs.Value(prefs.BOOL, False), + "download_conflict_resolution": prefs.Value(prefs.STRING, + config.SKIP_DOWNLOAD), + "backup_duplicate_overwrite": prefs.Value(prefs.BOOL, False), + "display_selection": prefs.Value(prefs.BOOL, True), + "display_size_column": prefs.Value(prefs.BOOL, True), + "display_filename_column": prefs.Value(prefs.BOOL, False), + "display_type_column": prefs.Value(prefs.BOOL, True), + "display_path_column": prefs.Value(prefs.BOOL, False), + "display_device_column": prefs.Value(prefs.BOOL, False), + "display_preview_folders": 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), + "job_codes": prefs.ListValue(prefs.STRING_LIST, [_('New York'), + _('Manila'), _('Prague'), _('Helsinki'), _('Wellington'), + _('Tehran'), _('Kampala'), _('Paris'), _('Berlin'), _('Sydney'), + _('Budapest'), _('Rome'), _('Moscow'), _('Delhi'), _('Warsaw'), + _('Jakarta'), _('Madrid'), _('Stockholm')]), + "synchronize_raw_jpg": prefs.Value(prefs.BOOL, False), + "vpaned_pos": prefs.Value(prefs.INT, 0), + "main_window_size_x": prefs.Value(prefs.INT, 0), + "main_window_size_y": prefs.Value(prefs.INT, 0), + "main_window_maximized": prefs.Value(prefs.INT, 0), + "show_warning_downloading_from_camera": prefs.Value(prefs.BOOL, True), + #~ "preview_zoom": prefs.Value(prefs.INT, zoom), + "generate_thumbnails": prefs.Value(prefs.BOOL, True), + } + + def __init__(self): + prefs.Preferences.__init__(self, config.GCONF_KEY, self.defaults) + + + def get_downloads_today_tracker(self): + return DownloadsTodayTracker(downloads_today_date = self.downloads_today[0], + downloads_today = self.downloads_today[1], + day_start = self.day_start + ) + + def set_downloads_today_from_tracker(self, downloads_today_tracker): + self.downloads_today = downloads_today_tracker.downloads_today + self.day_start = downloads_today_tracker.day_start + + def get_sample_job_code(self): + if self.job_codes: + return self.job_codes[0] + else: + return '' + + def _get_pref_lists(self): + return (self.image_rename, self.subfolder, self.video_rename, + self.video_subfolder) + + def _pref_list_uses_component(self, pref_list, pref_component, offset): + for i in range(0, len(pref_list), 3): + if pref_list[i+offset] == pref_component: + return True + return False + + def must_synchronize_raw_jpg(self): + """Returns True if synchronize_raw_jpg is True and photo renaming + uses sequence values""" + if self.synchronize_raw_jpg: + for s in LIST_SEQUENCE_L1: + if self._pref_list_uses_component(self.image_rename, s, 1): + return True + return False + + def any_pref_uses_stored_sequence_no(self): + """Returns True if any of the pref lists contain a stored sequence no""" + for pref_list in self._get_pref_lists(): + if self._pref_list_uses_component(pref_list, STORED_SEQ_NUMBER, 1): + return True + return False + + def any_pref_uses_session_sequece_no(self): + """Returns True if any of the pref lists contain a session sequence no""" + for pref_list in self._get_pref_lists(): + if self._pref_list_uses_component(pref_list, SESSION_SEQ_NUMBER, 1): + return True + return False + + def any_pref_uses_sequence_letter_value(self): + """Returns True if any of the pref lists contain a sequence letter""" + for pref_list in self._get_pref_lists(): + if self._pref_list_uses_component(pref_list, SEQUENCE_LETTER, 1): + return True + return False + + def reset(self): + """ + resets all preferences to default values + """ + + prefs.Preferences.reset(self) + self.program_version = __version__ + + + def pref_uses_job_code(self, pref_list): + """ Returns True if the particular preferences contains a job code""" + for i in range(0, len(pref_list), 3): + if pref_list[i] == JOB_CODE: + return True + return False + + def any_pref_uses_job_code(self): + """ Returns True if any of the preferences contain a job code""" + for pref_list in self._get_pref_lists(): + if self.pref_uses_job_code(pref_list): + return True + return False + + def most_recent_job_code(self): + if len(self.job_codes) > 0: + return self.job_codes[0] + else: + return None + + def get_pref_lists_by_file_type(self, file_type): + """ + Returns tuple of subfolder and file rename pref lists for the given + file type + """ + if file_type == rpdfile.FILE_TYPE_PHOTO: + return (self.subfolder, self.image_rename) + else: + return (self.video_subfolder, self.video_rename) + + def get_download_folder_for_file_type(self, file_type): + """ + Returns the download folder for the given file type + """ + if file_type == rpdfile.FILE_TYPE_PHOTO: + return self.download_folder + else: + return self.video_download_folder + + +class DownloadsTodayTracker: + """ + Handles tracking the number of downloads undertaken on any one day. + + When a day starts is flexible. See http://damonlynch.net/rapid/documentation/#renameoptions + """ + def __init__(self, downloads_today_date, downloads_today, day_start): + self.day_start = day_start # string + self.downloads_today = [downloads_today_date, str(downloads_today)] # two strings + + def get_and_maybe_reset_downloads_today(self): + v = self.get_downloads_today() + if v <= 0: + self.reset_downloads_today() + return v + + def get_downloads_today(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.get_day_start() + try: + adjusted_today = datetime.datetime.strptime("%s %s:%s" % (self.downloads_today[0], hour, minute), "%Y-%m-%d %H:%M") + except: + logger.critical("Failed to calculate date adjustment. Download today values appear to be corrupted: %s %s:%s", + self.downloads_today[0], hour, minute) + adjusted_today = None + + now = datetime.datetime.today() + + if adjusted_today is None: + return -1 + + if now < adjusted_today : + try: + return int(self.downloads_today[1]) + except ValueError: + logger.error("Invalid Downloads Today value. Resetting value to zero.") + self.get_downloads_today(self.downloads_today[0] , 0) + return 0 + else: + return -1 + + def get_raw_downloads_today(self): + """ + Gets value without changing it in any way, except to check for type convesion error. + If there is an error, then the value is reset + """ + try: + return int(self.downloads_today[1]) + except ValueError: + logger.critical("Downloads today value is corrupted: %s", self.downloads_today[1]) + self.downloads_today[1] = '0' + return 0 + + def set_raw_downloads_today_from_int(self, downloads_today): + self.downloads_today[1] = str(downloads_today) + + def set_raw_downloads_today_date(self, downloads_today_date): + self.downloads_today[0] = downloads_today_date + + def get_raw_downloads_today_date(self): + return self.downloads_today[0] + + def get_raw_day_start(self): + """ + Gets value without changing it in any way + """ + return self.day_start + + def get_day_start(self): + try: + t1, t2 = self.day_start.split(":") + return (int(t1), int(t2)) + except ValueError: + logger.error("'Start of day' preference value %s is corrupted. Resetting to midnight", self.day_start) + self.day_start = "0:0" + return 0, 0 + + def increment_downloads_today(self): + """ returns true if day changed """ + v = self.get_downloads_today() + if v >= 0: + self.set_downloads_today(self.downloads_today[0], v + 1) + return False + else: + self.reset_downloads_today(1) + return True + + def reset_downloads_today(self, value=0): + now = datetime.datetime.today() + hour, minute = self.get_day_start() + 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.set_downloads_today(date, value) + + def set_downloads_today(self, date, value=0): + self.downloads_today = [date, str(value)] + + def set_day_start(self, hour, minute): + self.day_start = "%s:%s" % (hour, minute) + + def log_vals(self): + logger.info("Date %s Value %s Day start %s", self.downloads_today[0], self.downloads_today[1], self.day_start) + + + +def check_prefs_for_validity(prefs): + """ + Checks preferences for validity (called at program startup) + + Returns tuple with two values: + 1. true if the passed in preferences are valid, else returns False + 2. message if prefs are invalid + """ + + + msg = '' + valid = True + tests = ((prefs.image_rename, pd.PhotoNamePrefs), + (prefs.subfolder, pd.PhotoSubfolderPrefs), + (prefs.video_rename, pd.VideoNamePrefs), + (prefs.video_subfolder, pd.VideoSubfolderPrefs)) + for pref, pref_widgets in tests: + p = pref_widgets(pref) + try: + p.check_prefs_for_validity() + except pd.PrefError as e: + valid = False + msg += e.msg + "\n" + + return (valid, msg) + +def insert_pref_lists(prefs, rpd_file): + """ + Convenience function to insert subfolder and file rename pref_lists for + the given file type. + + Returns the modified rpd_file + """ + subfolder_pref_list, name_pref_list = prefs.get_pref_lists_by_file_type(rpd_file.file_type) + rpd_file.subfolder_pref_list = subfolder_pref_list + rpd_file.name_pref_list = name_pref_list + return rpd_file + +def format_pref_list_for_pretty_print(pref_list): + """ returns a string useful for printing the preferences""" + + v = '' + + for i in range(0, len(pref_list), 3): + if (pref_list[i+1] or pref_list[i+2]): + c = ':' + else: + c = '' + s = "%s%s " % (pref_list[i], c) + + if pref_list[i+1]: + s = "%s%s" % (s, pref_list[i+1]) + if pref_list[i+2]: + s = "%s (%s)" % (s, pref_list[i+2]) + v += s + "\n" + return v + + diff --git a/rapid/problemnotification.py b/rapid/problemnotification.py index 8dc07d0..6238847 100755 --- a/rapid/problemnotification.py +++ b/rapid/problemnotification.py @@ -19,9 +19,7 @@ import sys import types -from common import Configi18n -global _ -_ = Configi18n._ +from gettext import gettext as _ # components diff --git a/rapid/rapid.py b/rapid/rapid.py index f41c79f..335db34 100755 --- a/rapid/rapid.py +++ b/rapid/rapid.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: latin1 -*- -### Copyright (C) 2007, 2008, 2009, 2010 Damon Lynch <damonlynch@gmail.com> +### Copyright (C) 2011 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 @@ -17,19 +17,8 @@ ### 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 types -import webbrowser -import operator import dbus import dbus.bus @@ -37,1549 +26,91 @@ 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 +from optparse import OptionParser +import gtk import gtk.gdk as gdk -import pango -import gobject - -try: - import gio - import glib - using_gio = True -except ImportError: - import gnomevfs - using_gio = False - -import prefs -import paths -import gnomeglade -from optparse import OptionParser +import webbrowser + +import sys, time, types, os, datetime +import gobject, pango, cairo, array, pangocairo, gio import pynotify -import idletube as tube +from multiprocessing import Process, Pipe, Queue, Event, Value, Array, current_process, log_to_stderr +from ctypes import c_int, c_bool, c_char -import config +import logging +logger = log_to_stderr() -from config import STATUS_CANNOT_DOWNLOAD, STATUS_DOWNLOADED, \ - STATUS_DOWNLOADED_WITH_WARNING, \ - STATUS_DOWNLOAD_FAILED, \ - STATUS_DOWNLOAD_PENDING, \ - STATUS_BACKUP_PROBLEM, \ - STATUS_NOT_DOWNLOADED, \ - STATUS_DOWNLOAD_AND_BACKUP_FAILED, \ - STATUS_WARNING - -import common -import misc -import higdefaults as hd +# Rapid Photo Downloader modules -from media import getDefaultPhotoLocation, getDefaultVideoLocation, \ - getDefaultBackupPhotoIdentifier, \ - getDefaultBackupVideoIdentifier +import rpdfile -import ValidatedEntry - -from media import CardMedia - -import media - -import metadata -import videometadata -from videometadata import DOWNLOAD_VIDEO - -import renamesubfolderprefs as rn import problemnotification as pn +import thumbnail as tn +import rpdmultiprocessing as rpdmp -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) - -try: - from dropshadow import image_to_pixbuf, pixbuf_to_image, DropShadow - DROP_SHADOW = True -except: - DROP_SHADOW = False - - -#~ DROP_SHADOW = False # for testing - -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') - -TINY_SCREEN = gtk.gdk.screen_height() <= config.TINY_SCREEN_HEIGHT -#~ TINY_SCREEN = True - -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 = selection_hbox = log_dialog = None - -job_code = None -need_job_code_for_renaming = False - -class ThreadManager: - """ - Manages the threads that actually download photos and videos - """ - _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 _isScanning(self, w): - return w.isAlive() and w.hasStarted and not w.scanComplete and not w.manuallyDisabled - - def _isDownloading(self, w): - return w.downloadStarted and w.isAlive() and not w.downloadComplete - - def _isPaused(self, w): - return w.downloadStarted and not w.running and not w.downloadComplete and not w.manuallyDisabled and w.isAlive() - - 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(): - #for some reason, very occassionally a thread that has been started shows up in this list, so must filter them out - if not w.isAlive(): - w.start() - - 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 getNotDownloadingAndNotFinishedWorkers(self): - for w in self._workers: - if w.hasStarted and not w.downloadStarted and not self._isFinished(w): - yield w - - - def noReadyToStartWorkers(self): - n = 0 - for w in self._workers: - if self._isReadyToStart(w): - n += 1 - return n - - def noScanningWorkers(self): - n = 0 - for w in self._workers: - if self._isScanning(w): - n += 1 - return n - - def getScanningWorkers(self): - for w in self._workers: - if self._isScanning(w): - yield w - - def scanComplete(self, threads): - """ - Returns True only if the list of threads have completed their scan - """ - for thread_id in threads: - if not self[thread_id].scanComplete: - return False - return True - - 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 getPausedDownloadingWorkers(self): - for w in self._workers: - if self._isPaused(w): - yield w - - def getWaitingForJobCodeWorkers(self): - for w in self._workers: - if w.waitingForJobCode: - yield w - - def getAutoStartWorkers(self): - for w in self._workers: - if w.autoStart: - 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 +import preferencesdialog +import prefsrapid - def noRunningWorkers(self): - i = 0 - for w in self._workers: - if w.hasStarted and w.isAlive(): - i += 1 - return i - - def noPausedWorkers(self): - i = 0 - for w in self._workers: - if self._isPaused(w): - 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): - if TINY_SCREEN: - zoom = 120 - else: - zoom = config.MIN_THUMBNAIL_SIZE * 2 - - defaults = { - "program_version": prefs.Value(prefs.STRING, ""), - "download_folder": prefs.Value(prefs.STRING, - getDefaultPhotoLocation()), - "video_download_folder": prefs.Value(prefs.STRING, - getDefaultVideoLocation()), - "subfolder": prefs.ListValue(prefs.STRING_LIST, rn.DEFAULT_SUBFOLDER_PREFS), - "video_subfolder": prefs.ListValue(prefs.STRING_LIST, rn.DEFAULT_VIDEO_SUBFOLDER_PREFS), - "image_rename": prefs.ListValue(prefs.STRING_LIST, [rn.FILENAME, - rn.NAME_EXTENSION, - rn.ORIGINAL_CASE]), - "video_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), - "device_whitelist": prefs.ListValue(prefs.STRING_LIST, ['']), - "device_blacklist": prefs.ListValue(prefs.STRING_LIST, ['']), - "backup_images": prefs.Value(prefs.BOOL, False), - "backup_device_autodetection": prefs.Value(prefs.BOOL, True), - "backup_identifier": prefs.Value(prefs.STRING, - getDefaultBackupPhotoIdentifier()), - "video_backup_identifier": prefs.Value(prefs.STRING, - getDefaultBackupVideoIdentifier()), - "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), - "auto_delete": prefs.Value(prefs.BOOL, False), - "download_conflict_resolution": prefs.Value(prefs.STRING, - config.SKIP_DOWNLOAD), - "backup_duplicate_overwrite": prefs.Value(prefs.BOOL, False), - "display_selection": prefs.Value(prefs.BOOL, True), - "display_size_column": prefs.Value(prefs.BOOL, True), - "display_filename_column": prefs.Value(prefs.BOOL, False), - "display_type_column": prefs.Value(prefs.BOOL, True), - "display_path_column": prefs.Value(prefs.BOOL, False), - "display_device_column": prefs.Value(prefs.BOOL, False), - "display_preview_folders": 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), - "job_codes": prefs.ListValue(prefs.STRING_LIST, [_('New York'), - _('Manila'), _('Prague'), _('Helsinki'), _('Wellington'), - _('Tehran'), _('Kampala'), _('Paris'), _('Berlin'), _('Sydney'), - _('Budapest'), _('Rome'), _('Moscow'), _('Delhi'), _('Warsaw'), - _('Jakarta'), _('Madrid'), _('Stockholm')]), - "synchronize_raw_jpg": prefs.Value(prefs.BOOL, False), - "hpaned_pos": prefs.Value(prefs.INT, 0), - "vpaned_pos": prefs.Value(prefs.INT, 0), - "main_window_size_x": prefs.Value(prefs.INT, 0), - "main_window_size_y": prefs.Value(prefs.INT, 0), - "main_window_maximized": prefs.Value(prefs.INT, 0), - "show_warning_downloading_from_camera": prefs.Value(prefs.BOOL, True), - "preview_zoom": prefs.Value(prefs.INT, zoom), - } - - 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 - - def getSampleJobCode(self): - if self.job_codes: - return self.job_codes[0] - else: - return '' - - def reset(self): - """ - resets all preferences to default values - """ - - prefs.Preferences.reset(self) - self.program_version = __version__ - -class ImageRenameTable(tpm.TablePlusMinus): - - def __init__(self, parentApp, adjustScrollWindow): - - tpm.TablePlusMinus.__init__(self, 1, 3) - self.parentApp = parentApp - self.adjustScrollWindow = adjustScrollWindow - if not hasattr(self, "errorTitle"): - self.errorTitle = _("Error in Photo Rename preferences") - - self.table_type = self.errorTitle[len("Error in "):] - self.i = 0 - - if adjustScrollWindow: - self.scrollBar = self.adjustScrollWindow.get_vscrollbar() - #this next line does not work on early versions of pygtk :( - self.scrollBar.connect('visibility-notify-event', self.scrollbar_visibility_change) - self.connect("size-request", self.size_adjustment) - self.connect("add", self.size_adjustment) - self.connect("remove", self.size_adjustment) - - # get scrollbar thickness from parent app scrollbar - very hackish, but what to do?? - self.bump = 16# self.parentApp.parentApp.image_scrolledwindow.get_hscrollbar().allocation.height - self.haveVerticalScrollbar = False - - # 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() - self.prefsFactory.setDownloadStartTime(datetime.datetime.now()) - - 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." + "\n") - 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 scrollbar_visibility_change(self, widget, event): - if event.state == gdk.VISIBILITY_UNOBSCURED: - self.haveVerticalScrollbar = True - self.adjustScrollWindow.set_size_request(self.adjustScrollWindow.allocation.width + self.bump, -1) - - - def size_adjustment(self, widget, arg2): - """ - Adjust scrolledwindow width in preferences dialog to reflect width of image rename table - - The algorithm is complicated by the need to take into account the presence of a vertical scrollbar, - which might be added as the user adds more rows - - The pygtk code behaves inconsistently depending on the pygtk version - """ - - if self.adjustScrollWindow: - self.haveVerticalScrollbar = self.scrollBar.allocation.width > 1 or self.haveVerticalScrollbar - if not self.haveVerticalScrollbar: - if self.allocation.width > self.adjustScrollWindow.allocation.width: - self.adjustScrollWindow.set_size_request(self.allocation.width, -1) - else: - if self.allocation.width > self.adjustScrollWindow.allocation.width - self.bump: - self.adjustScrollWindow.set_size_request(self.allocation.width + self.bump, -1) - self.bump = 0 - - 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 updateExampleJobCode(self): - job_code = self.parentApp.prefs.getSampleJobCode() - if not job_code: - job_code = _('Job code') - self.prefsFactory.setJobCode(job_code) - - 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 VideoRenameTable(ImageRenameTable): - def __init__(self, parentApp, adjustScollWindow): - self.errorTitle = _("Error in Video Rename preferences") - ImageRenameTable.__init__(self, parentApp, adjustScollWindow) - - def getParentAppPrefs(self): - self.prefList = self.parentApp.prefs.video_rename - - def getPrefsFactory(self): - self.prefsFactory = rn.VideoRenamePreferences(self.prefList, self, - sequences = sequences) - - def updateParentAppPrefs(self): - self.parentApp.prefs.video_rename = self.prefList +import tableplusminus as tpm +import generatename as gn - def updateExample(self): - self.parentApp.updateVideoRenameExample() +import downloadtracker -class SubfolderTable(ImageRenameTable): - def __init__(self, parentApp, adjustScollWindow): - self.errorTitle = _("Error in Photo Download Subfolders preferences") - ImageRenameTable.__init__(self, parentApp, adjustScollWindow) +from metadatavideo import DOWNLOAD_VIDEO +import metadataphoto +import metadatavideo - 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 +import scan as scan_process +import copyfiles +import subfolderfile +import backupfile - def updateExample(self): - self.parentApp.updatePhotoDownloadFolderExample() - -class VideoSubfolderTable(ImageRenameTable): - def __init__(self, parentApp, adjustScollWindow): - self.errorTitle = _("Error in Video Download Subfolders preferences") - ImageRenameTable.__init__(self, parentApp, adjustScollWindow) - - def getParentAppPrefs(self): - self.prefList = self.parentApp.prefs.video_subfolder - - def getPrefsFactory(self): - self.prefsFactory = rn.VideoSubfolderPreferences(self.prefList, self) - - def updateParentAppPrefs(self): - self.parentApp.prefs.video_subfolder = self.prefList +import errorlog - def updateExample(self): - self.parentApp.updateVideoDownloadFolderExample() - -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 - - parentApp.preferencesDialogDisplayed = True - - self.parentApp = parentApp - - self._setupTabSelector() - - self._setupControlSpacing() - - if DOWNLOAD_VIDEO: - self.file_types = _("photos and videos") - else: - self.file_types = _("photos") +import device as dv +import utilities - # get example photo and video data - try: - w = workers.firstWorkerReadyToDownload() - mediaFile = w.firstImage() - self.sampleImageName = mediaFile.name - # assume the metadata is already read - self.sampleImage = mediaFile.metadata - except: - self.sampleImage = metadata.DummyMetaData() - self.sampleImageName = 'IMG_0524.CR2' - - try: - mediaFile = w.firstVideo() - self.sampleVideoName = mediaFile.name - self.sampleVideo = mediaFile.metadata - self.videoFallBackDate = mediaFile.modificationTime - except: - self.sampleVideo = videometadata.DummyMetaData() - self.sampleVideoName = 'MVI_1379.MOV' - self.videoFallBackDate = datetime.datetime.now() - - - # setup tabs - self._setupPhotoDownloadFolderTab() - self._setupImageRenameTab() - self._setupVideoDownloadFolderTab() - self._setupVideoRenameTab() - self._setupRenameOptionsTab() - self._setupJobCodeTab() - self._setupDeviceTab() - self._setupBackupTab() - self._setupAutomationTab() - self._setupErrorTab() - - if not DOWNLOAD_VIDEO: - self.disableVideoControls() - - 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 photo 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.updatePhotoDownloadFolderExample() - - def on_video_download_folder_filechooser_button_selection_changed(self, widget): - self.prefs.video_download_folder = widget.get_current_folder() - self.updateVideoDownloadFolderExample() - - 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 - """ - - self._setupTableSpacing(self.download_folder_table) - self._setupTableSpacing(self.video_download_folder_table) - self.download_folder_table.set_row_spacing(2, - hd.VERTICAL_CONTROL_SPACE) - self.video_download_folder_table.set_row_spacing(2, - hd.VERTICAL_CONTROL_SPACE) - self._setupTableSpacing(self.rename_example_table) - self._setupTableSpacing(self.video_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) - - - 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 _setupVideoSubfolderTable(self): - self.video_subfolder_table = VideoSubfolderTable(self, None) - self.video_subfolder_vbox.pack_start(self.video_subfolder_table) - self.video_subfolder_table.show_all() - - def _setupPhotoDownloadFolderTab(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.updatePhotoDownloadFolderExample() - - def _setupVideoDownloadFolderTab(self): - self.video_download_folder_filechooser_button = gtk.FileChooserButton( - _("Select a folder to download videos to")) - self.video_download_folder_filechooser_button.set_current_folder( - self.prefs.video_download_folder) - self.video_download_folder_filechooser_button.set_action( - gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) - self.video_download_folder_filechooser_button.connect("selection-changed", - self.on_video_download_folder_filechooser_button_selection_changed) - - self.video_download_folder_table.attach( - self.video_download_folder_filechooser_button, - 2, 3, 2, 3, yoptions = gtk.SHRINK) - self.video_download_folder_filechooser_button.show() - self._setupVideoSubfolderTable() - self.updateVideoDownloadFolderExample() - - def _setupImageRenameTab(self): +import config +__version__ = config.version - 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 _setupVideoRenameTab(self): +import paths - self.video_rename_table = VideoRenameTable(self, self.video_rename_scrolledwindow) - self.video_rename_table_vbox.pack_start(self.video_rename_table) - self.video_rename_table.show_all() - self.video_original_name_label.set_markup("<i>%s</i>" % self.sampleVideoName) - self.updateVideoRenameExample() - - def _setupRenameOptionsTab(self): - - # sequence numbers - 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.synchronize_raw_jpg_checkbutton.set_active( - self.prefs.synchronize_raw_jpg) - - #compatibility - self.strip_characters_checkbutton.set_active( - self.prefs.strip_characters) - - def _setupJobCodeTab(self): - self.job_code_liststore = gtk.ListStore(str) - column = gtk.TreeViewColumn() - rentext = gtk.CellRendererText() - rentext.connect('edited', self.on_job_code_edited) - rentext .set_property('editable', True) - - column.pack_start(rentext, expand=0) - column.set_attributes(rentext, text=0) - self.job_code_treeview_column = column - self.job_code_treeview.append_column(column) - self.job_code_treeview.props.model = self.job_code_liststore - for code in self.prefs.job_codes: - self.job_code_liststore.append((code, )) - - # set multiple selections - self.job_code_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) - - self.remove_all_job_code_button.set_image(gtk.image_new_from_stock( - gtk.STOCK_CLEAR, - gtk.ICON_SIZE_BUTTON)) - def _setupDeviceTab(self): - - self.device_location_filechooser_button = gtk.FileChooserButton( - _("Select a folder containing %(file_types)s") % {'file_types':self.file_types}) - 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 %(file_types)s") % {'file_types':self.file_types}) - 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, 8, 9, yoptions = gtk.SHRINK) - self.backup_folder_filechooser_button.show() - self.backup_identifier_entry.set_text(self.prefs.backup_identifier) - self.video_backup_identifier_entry.set_text(self.prefs.video_backup_identifier) - - #setup controls for manipulating sensitivity - self._backupControls0 = [self.auto_detect_backup_checkbutton] - 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 - - self._backupVideoControls = [self.video_backup_identifier_label, - self.video_backup_identifier_entry] - - #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) - self.auto_delete_checkbutton.set_active( - self.prefs.auto_delete) - - - def _setupErrorTab(self): - 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_duplicate_overwrite: - self.backup_duplicate_overwrite_radiobutton.set_active(True) - else: - self.backup_duplicate_skip_radiobutton.set_active(True) +import gettext +gettext.bindtextdomain(config.APP_NAME) +gettext.textdomain(config.APP_NAME) - - def updateExampleFileName(self, display_table, rename_table, sample, sampleName, example_label, fallback_date = None): - problem = pn.Problem() - if hasattr(self, display_table): - rename_table.updateExampleJobCode() - rename_table.prefsFactory.initializeProblem(problem) - name = rename_table.prefsFactory.generateNameUsingPreferences( - sample, sampleName, - self.prefs.strip_characters, sequencesPreliminary=False, fallback_date=fallback_date) - else: - name = '' - - # since this is markup, escape it - text = "<i>%s</i>" % common.escape(name) - - if problem.has_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 metadata to fully generate the name. Please use other renaming options.</i>") +from gettext import gettext as _ - example_label.set_markup(text) - - def updateImageRenameExample(self): - """ - Displays example image name to the user - """ - self.updateExampleFileName('rename_table', self.rename_table, self.sampleImage, self.sampleImageName, self.new_name_label) - - def updateVideoRenameExample(self): - """ - Displays example video name to the user - """ - self.updateExampleFileName('video_rename_table', self.video_rename_table, self.sampleVideo, self.sampleVideoName, self.video_new_name_label, self.videoFallBackDate) - - def updateDownloadFolderExample(self, display_table, subfolder_table, download_folder, sample, sampleName, example_download_path_label, subfolder_warning_label, fallback_date = None): - """ - Displays example subfolder name(s) to the user - """ - - problem = pn.Problem() - if hasattr(self, display_table): - subfolder_table.updateExampleJobCode() - subfolder_table.prefsFactory.initializeProblem(problem) - path = subfolder_table.prefsFactory.generateNameUsingPreferences( - sample, sampleName, - self.prefs.strip_characters, fallback_date = fallback_date) - else: - path = '' - - text = os.path.join(download_folder, path) - # since this is markup, escape it - path = common.escape(text) - if problem.has_problem(): - warning = _("<i><b>Warning:</b> There is insufficient metadata 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 - example_download_path_label.set_markup(_("<i>Example: %s</i>") % text) - subfolder_warning_label.set_markup(warning) - - def updatePhotoDownloadFolderExample(self): - if hasattr(self, 'subfolder_table'): - self.updateDownloadFolderExample('subfolder_table', self.subfolder_table, self.prefs.download_folder, self.sampleImage, self.sampleImageName, self.example_photo_download_path_label, self.photo_subfolder_warning_label) - - def updateVideoDownloadFolderExample(self): - if hasattr(self, 'video_subfolder_table'): - self.updateDownloadFolderExample('video_subfolder_table', self.video_subfolder_table, self.prefs.video_download_folder, self.sampleVideo, self.sampleVideoName, self.example_video_download_path_label, self.video_subfolder_warning_label, self.videoFallBackDate) - - 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): - # do not update value if a download is occurring - it will mess it up! - if workers.noDownloadingWorkers() <> 0: - cmd_line(_("Downloads today value not updated, as a download is currently occurring")) - else: - 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): - # do not update value if a download is occurring - it will mess it up! - if workers.noDownloadingWorkers() <> 0: - cmd_line(_("Stored number value not updated, as a download is currently occurring")) - else: - 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() +from utilities import format_size_for_user +from utilities import register_iconsets - def _updateSubfolderPrefOnError(self, newPrefList): - self.prefs.subfolder = newPrefList - def _updateVideoSubfolderPrefOnError(self, newPrefList): - self.prefs.video_subfolder = newPrefList - - - def checkSubfolderValuesValidOnExit(self, usersPrefList, updatePrefFunction, filetype, defaultPrefList): - """ - Checks that the user has not entered in any inappropriate values - - If they have, filters out bad values and warns the user - """ - filtered, prefList = rn.filterSubfolderPreferences(usersPrefList) - if filtered: - cmd_line(_("The %(filetype)s subfolder preferences had some unnecessary values removed.") % {'filetype': filetype}) - if prefList: - updatePrefFunction(prefList) - else: - #Preferences list is now empty - msg = _("The %(filetype)s subfolder preferences entered are invalid and cannot be used.\nThey will be reset to their default values.") % {'filetype': filetype} - sys.stderr.write(msg + "\n") - misc.run_dialog(PROGRAM_NAME, msg) - updatePrefFunction(self.prefs.get_default(defaultPrefList)) - - 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") - self.prefs.video_backup_identifier = self.video_backup_identifier_entry.get_property("text") - - #check subfolder preferences for bad values - self.checkSubfolderValuesValidOnExit(self.prefs.subfolder, self._updateSubfolderPrefOnError, _("photo"), "subfolder") - self.checkSubfolderValuesValidOnExit(self.prefs.video_subfolder, self._updateVideoSubfolderPrefOnError, _("video"), "video_subfolder") +from config import STATUS_CANNOT_DOWNLOAD, STATUS_DOWNLOADED, \ + STATUS_DOWNLOADED_WITH_WARNING, \ + STATUS_DOWNLOAD_FAILED, \ + STATUS_DOWNLOAD_PENDING, \ + STATUS_BACKUP_PROBLEM, \ + STATUS_NOT_DOWNLOADED, \ + STATUS_DOWNLOAD_AND_BACKUP_FAILED, \ + STATUS_WARNING - self.widget.destroy() - self.parentApp.preferencesDialogDisplayed = False - self.parentApp.postPreferenceChange() - - - - - def on_add_job_code_button_clicked(self, button): - j = JobCodeDialog(self.widget, self.prefs.job_codes, None, self.add_job_code, False, True, True) - +DOWNLOADED = [STATUS_DOWNLOADED, STATUS_DOWNLOADED_WITH_WARNING, STATUS_BACKUP_PROBLEM] - def add_job_code(self, dialog, userChoseCode, job_code, autoStart, downloadSelected): - dialog.destroy() - if userChoseCode: - if job_code and job_code not in self.prefs.job_codes: - self.job_code_liststore.prepend((job_code, )) - self.update_job_codes() - selection = self.job_code_treeview.get_selection() - selection.unselect_all() - selection.select_path((0, )) - #scroll to the top - adjustment = self.job_code_scrolledwindow.get_vadjustment() - adjustment.set_value(adjustment.lower) - - def on_remove_job_code_button_clicked(self, button): - """ remove selected job codes (can be multiple selection)""" - selection = self.job_code_treeview.get_selection() - model, selected = selection.get_selected_rows() - iters = [model.get_iter(path) for path in selected] - # only delete if a jobe code is selected - if iters: - no = len(iters) - path = None - for i in range(0, no): - iter = iters[i] - if i == no - 1: - path = model.get_path(iter) - model.remove(iter) - - # now that we removed the selection, play nice with - # the user and select the next item - selection.select_path(path) - - # if there was no selection that meant the user - # removed the last entry, so we try to select the - # last item - if not selection.path_is_selected(path): - row = path[0]-1 - # test case for empty lists - if row >= 0: - selection.select_path((row,)) - - self.update_job_codes() - self.updateImageRenameExample() - self.updateVideoRenameExample() - self.updatePhotoDownloadFolderExample() - self.updateVideoDownloadFolderExample() - - def on_remove_all_job_code_button_clicked(self, button): - j = RemoveAllJobCodeDialog(self.widget, self.remove_all_job_code) - - def remove_all_job_code(self, dialog, userSelected): - dialog.destroy() - if userSelected: - self.job_code_liststore.clear() - self.update_job_codes() - self.updateImageRenameExample() - self.updateVideoRenameExample() - self.updatePhotoDownloadFolderExample() - self.updateVideoDownloadFolderExample() - - def on_job_code_edited(self, widget, path, new_text): - iter = self.job_code_liststore.get_iter(path) - self.job_code_liststore.set_value(iter, 0, new_text) - self.update_job_codes() - self.updateImageRenameExample() - self.updateVideoRenameExample() - self.updatePhotoDownloadFolderExample() - self.updateVideoDownloadFolderExample() - - def update_job_codes(self): - """ update preferences with list of job codes""" - job_codes = [] - for row in self.job_code_liststore: - job_codes.append(row[0]) - self.prefs.job_codes = job_codes - - 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_delete_checkbutton_toggled(self, checkbutton): - self.prefs.auto_delete = 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_treeview_cursor_changed(self, tree): - path, column = tree.get_cursor() - self.notebook.set_current_page(path[0]) - - def on_synchronize_raw_jpg_checkbutton_toggled(self, check_button): - self.prefs.synchronize_raw_jpg = check_button.get_active() - - def on_strip_characters_checkbutton_toggled(self, check_button): - self.prefs.strip_characters = check_button.get_active() - self.updateImageRenameExample() - self.updatePhotoDownloadFolderExample() - self.updateVideoDownloadFolderExample() - - 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 + self._backupVideoControls: - 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) - for c in self._backupVideoControls: - c.set_sensitive(False) - if DOWNLOAD_VIDEO: - for c in self._backupVideoControls: - c.set_sensitive(True) - else: - for c in self._backupControls1: - c.set_sensitive(False) - for c in self._backupControls2: - c.set_sensitive(True) - if DOWNLOAD_VIDEO: - for c in self._backupVideoControls: - c.set_sensitive(False) - - def disableVideoControls(self): - """ - Disables video preferences if video downloading is disabled - (probably because the appropriate libraries to enable - video metadata extraction are not installed) - """ - controls = [self.example_video_filename_label, - self.original_video_filename_label, - self.new_video_filename_label, - self.video_new_name_label, - self.video_original_name_label, - self.video_rename_scrolledwindow, - self.video_folders_hbox, - self.video_backup_identifier_label, - self.video_backup_identifier_entry - ] - for c in controls: - c.set_sensitive(False) - - self.videos_cannot_be_downloaded_label.show() - self.folder_videos_cannot_be_downloaded_label.show() - self.folder_videos_cannot_be_downloaded_hbox.show() - - 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_video_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. - drive1 = 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. - drive2 = os.path.join(config.MEDIA_LOCATION, _("externaldrive2")) - - path = os.path.join(drive1, self.backup_identifier_entry.get_text()) - path2 = os.path.join(drive2, self.backup_identifier_entry.get_text()) - path3 = os.path.join(drive2, self.video_backup_identifier_entry.get_text()) - path = common.escape(path) - path2 = common.escape(path2) - path3 = common.escape(path3) - if DOWNLOAD_VIDEO: - example = "<i>%s</i>\n<i>%s</i>\n<i>%s</i>" % (path, path2, path3) - else: - example = "<i>%s</i>\n<i>%s</i>" % (path, path2) - self.example_backup_path_label.set_markup(example) +#Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html +PROGRAM_NAME = _('Rapid Photo Downloader') +__version__ = config.version - -def file_types_by_number(noImages, noVideos): - """ - returns a string to be displayed to the user that can be used - to show if a value refers to photos or videos or both, or just one - of each - """ - if (noVideos > 0) and (noImages > 0): - v = _('photos and videos') - elif (noVideos == 0) and (noImages == 0): - v = _('photos or videos') - elif noVideos > 0: - if noVideos > 1: - v = _('videos') - else: - v = _('video') - else: - if noImages > 1: - v = _('photos') - else: - v = _('photo') - return v - def date_time_human_readable(date, with_line_break=True): if with_line_break: return _("%(date)s\n%(time)s") % {'date':date.strftime("%x"), 'time':date.strftime("%X")} else: return _("%(date)s %(time)s") % {'date':date.strftime("%x"), 'time':date.strftime("%X")} -def time_subseconds_human_readable(date, subseconds): - return _("%(hour)s:%(minute)s:%(second)s:%(subsecond)s") % \ - {'hour':date.strftime("%H"), - 'minute':date.strftime("%M"), - 'second':date.strftime("%S"), - 'subsecond': subseconds} - def date_time_subseconds_human_readable(date, subseconds): return _("%(date)s %(hour)s:%(minute)s:%(second)s:%(subsecond)s") % \ {'date':date.strftime("%x"), @@ -1588,1498 +119,22 @@ def date_time_subseconds_human_readable(date, subseconds): 'second':date.strftime("%S"), 'subsecond': subseconds} -def generateSubfolderAndName(mediaFile, problem, subfolderPrefsFactory, - renamePrefsFactory, - nameUsesJobCode, subfolderUsesJobCode, - strip_characters, fallback_date): - - subfolderPrefsFactory.initializeProblem(problem) - mediaFile.sampleSubfolder = subfolderPrefsFactory.generateNameUsingPreferences( - mediaFile.metadata, mediaFile.name, - strip_characters, - fallback_date = fallback_date) - - mediaFile.samplePath = os.path.join(mediaFile.downloadFolder, mediaFile.sampleSubfolder) - - renamePrefsFactory.initializeProblem(problem) - mediaFile.sampleName = renamePrefsFactory.generateNameUsingPreferences( - mediaFile.metadata, mediaFile.name, strip_characters, - sequencesPreliminary=False, - fallback_date = fallback_date) - - if not (mediaFile.sampleName or nameUsesJobCode) or not (mediaFile.sampleSubfolder or subfolderUsesJobCode): - if not (mediaFile.sampleName or nameUsesJobCode) and not (mediaFile.sampleSubfolder or subfolderUsesJobCode): - area = _("subfolder and filename") - elif not (mediaFile.sampleName or nameUsesJobCode): - area = _("filename") - else: - area = _("subfolder") - problem.add_problem(None, pn.ERROR_IN_NAME_GENERATION, {'filetype': mediaFile.displayNameCap, 'area': area}) - problem.add_extra_detail(pn.NO_DATA_TO_NAME, {'filetype': area}) - mediaFile.problem = problem - mediaFile.status = STATUS_CANNOT_DOWNLOAD - elif problem.has_problem(): - mediaFile.problem = problem - mediaFile.status = STATUS_WARNING - else: - mediaFile.status = STATUS_NOT_DOWNLOADED - -def getGenericPhotoImage(): - return gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/photo.png')) - -def getGenericVideoImage(): - return gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/video.png')) -class NeedAJobCode(): +class DeviceCollection(gtk.TreeView): """ - Convenience class to check whether a job code is missing for a given - file type (photo or video) + TreeView display of devices and how many files have been copied, shown + immediately under the menu in the main application window. """ - def __init__(self, prefs): - self.imageRenameUsesJobCode = rn.usesJobCode(prefs.image_rename) - self.imageSubfolderUsesJobCode = rn.usesJobCode(prefs.subfolder) - self.videoRenameUsesJobCode = rn.usesJobCode(prefs.video_rename) - self.videoSubfolderUsesJobCode = rn.usesJobCode(prefs.video_subfolder) - - def needAJobCode(self, job_code, is_image): - if is_image: - return not job_code and (self.imageRenameUsesJobCode or self.imageSubfolderUsesJobCode) - else: - return not job_code and (self.videoRenameUsesJobCode or self.videoSubfolderUsesJobCode) - - -class CopyPhotos(Thread): - """Copies photos from source to destination, backing up if needed""" - def __init__(self, thread_id, parentApp, fileRenameLock, fileSequenceLock, - statsLock, downloadedFilesLock, - 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.downloadedFilesLock = downloadedFilesLock - - self.downloadStats = downloadStats - - self.hasStarted = False - self.doNotStart = False - self.waitingForJobCode = False - - self.autoStart = autoStart - self.cardMedia = cardMedia - - self.initializeDisplay(thread_id, self.cardMedia) - - self.scanComplete = self.downloadStarted = self.downloadComplete = False - - # Need to account for situations where the user adjusts their preferences when the program is scanning - # Here the sample filenames and paths will be out of date, and they will need to be updated - # This flag indicates whether that is the case or not - self.scanResultsStale = False # name and subfolder - self.scanResultsStaleDownloadFolder = False #download folder only - - self.noErrors = self.noWarnings = 0 - self.videoTempWorkingDir = self.photoTempWorkingDir = '' - - if DOWNLOAD_VIDEO: - self.types_searched_for = _('photos or videos') - else: - self.types_searched_for = _('photos') - - Thread.__init__(self) - - - def initializeDisplay(self, thread_id, cardMedia = None): + def __init__(self, parent_app): - if self.cardMedia: - media_collection_treeview.addCard(thread_id, self.cardMedia.prettyName(), - '', progress=0.0, - # This refers to when a device like a hard drive is having its contents scanned, - # looking for photos or videos. It is visible initially in the progress bar for each device - # (which normally holds "x photos and videos"). - # It maybe displayed only briefly if the contents of the device being scanned is small. - progressBarText=_('scanning...')) - - def firstImage(self): - """ - returns class mediaFile of the first photo - """ - mediaFile = self.cardMedia.firstImage() - return mediaFile - - def firstVideo(self): - """ - returns class mediaFile of the first video - """ - mediaFile = self.cardMedia.firstVideo() - return mediaFile - - 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 - """ - - def checkPrefs(prefsFactory): - try: - prefsFactory.checkPrefsForValidity() - except (rn.PrefValueInvalidError, rn.PrefLengthError, - rn.PrefValueKeyComboError, rn.PrefKeyError), e: - if notifyOnError: - self.handlePreferencesError(e, prefsFactory) - raise rn.PrefError - - self.prefs = self.parentApp.prefs - - #Image and Video filename preferences - sample_download_start_time = datetime.datetime.now() - - self.imageRenamePrefsFactory = rn.ImageRenamePreferences(self.prefs.image_rename, self, - self.fileSequenceLock, sequences) - self.imageRenamePrefsFactory.setDownloadStartTime(sample_download_start_time) - checkPrefs(self.imageRenamePrefsFactory) - - self.videoRenamePrefsFactory = rn.VideoRenamePreferences(self.prefs.video_rename, self, - self.fileSequenceLock, sequences) - self.videoRenamePrefsFactory.setDownloadStartTime(sample_download_start_time) - checkPrefs(self.videoRenamePrefsFactory) - - #Image and Video subfolder preferences - - self.subfolderPrefsFactory = rn.SubfolderPreferences(self.prefs.subfolder, self) - self.subfolderPrefsFactory.setDownloadStartTime(sample_download_start_time) - checkPrefs(self.subfolderPrefsFactory) - - self.videoSubfolderPrefsFactory = rn.VideoSubfolderPreferences(self.prefs.video_subfolder, self) - self.videoSubfolderPrefsFactory.setDownloadStartTime(sample_download_start_time) - checkPrefs(self.videoSubfolderPrefsFactory) - - # 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 checkDownloadPath(path): - """ - Checks to see if download folder exists. - - Creates it if it does not exist. - - Returns False if the path could not be created. - """ - - try: - if not os.path.isdir(path): - os.makedirs(path) - return True - - except: - display_queue.put((media_collection_treeview.removeCard, (self.thread_id, ))) - msg = _("The following download path could not be created:\n") - msg += _("%(path)s: ") % {'path': path} - logError(config.CRITICAL_ERROR, _("Download cannot proceed"), msg) - cmd_line(_("Download cannot proceed")) - cmd_line(msg) - display_queue.put((self.parentApp.downloadFailed, (self.thread_id, ))) - display_queue.close("rw") - return False - - 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) - display_queue.put((self.parentApp.downloadFailed, (self.thread_id, ))) - display_queue.close("rw") - return False - - - - def scanMedia(): - """ - Scans media for photos and videos - """ - - # load images to display for when a thumbnail cannot be extracted or created - - self.photoThumbnail = getGenericPhotoImage() - self.videoThumbnail = getGenericVideoImage() - - imageRenameUsesJobCode = rn.usesJobCode(self.prefs.image_rename) - imageSubfolderUsesJobCode = rn.usesJobCode(self.prefs.subfolder) - videoRenameUsesJobCode = rn.usesJobCode(self.prefs.video_rename) - videoSubfolderUsesJobCode = rn.usesJobCode(self.prefs.video_subfolder) - - def loadFileMetadata(mediaFile): - """ - loads the metadate for the file, and additional information if required - """ - - problem = pn.Problem() - try: - mediaFile.loadMetadata() - except: - mediaFile.status = STATUS_CANNOT_DOWNLOAD - mediaFile.metadata = None - problem.add_problem(None, pn.CANNOT_DOWNLOAD_BAD_METADATA, {'filetype': mediaFile.displayNameCap}) - mediaFile.problem = problem - else: - # generate sample filename and subfolder - if mediaFile.isImage: - fallback_date = None - subfolderPrefsFactory = self.subfolderPrefsFactory - renamePrefsFactory = self.imageRenamePrefsFactory - nameUsesJobCode = imageRenameUsesJobCode - subfolderUsesJobCode = imageSubfolderUsesJobCode - else: - fallback_date = mediaFile.modificationTime - subfolderPrefsFactory = self.videoSubfolderPrefsFactory - renamePrefsFactory = self.videoRenamePrefsFactory - nameUsesJobCode = videoRenameUsesJobCode - subfolderUsesJobCode = videoSubfolderUsesJobCode - - generateSubfolderAndName(mediaFile, problem, subfolderPrefsFactory, renamePrefsFactory, - nameUsesJobCode, subfolderUsesJobCode, - self.prefs.strip_characters, fallback_date) - # generate thumbnail - mediaFile.generateThumbnail(self.videoTempWorkingDir) - - if mediaFile.thumbnail is None: - addGenericThumbnail(mediaFile) - - - def addGenericThumbnail(mediaFile): - """ - Adds a generic thumbnail to the mediafile, which - can be very useful when previews are disabled - """ - mediaFile.genericThumbnail = True - if mediaFile.isImage: - mediaFile.thumbnail = self.photoThumbnail - else: - mediaFile.thumbnail = self.videoThumbnail - - def downloadable(name): - isImage = media.isImage(name) - isVideo = media.isVideo(name) - download = (DOWNLOAD_VIDEO and (isImage or isVideo) or - ((not DOWNLOAD_VIDEO) and isImage)) - return (download, isImage, isVideo) - - def addFile(name, path, size, modificationTime, device, volume, isImage): - """ - Add an image or video to the list of scanned files to be shown to the user for potential downloading - """ - - if isImage: - downloadFolder = self.prefs.download_folder - else: - downloadFolder = self.prefs.video_download_folder - - mediaFile = media.MediaFile(self.thread_id, name, path, size, modificationTime, device, downloadFolder, volume, isImage) - loadFileMetadata(mediaFile) - # modificationTime is very useful for quick sorting - imagesAndVideos.append((mediaFile, modificationTime)) - display_queue.put((self.parentApp.addFile, (mediaFile,))) - - if isImage: - self.noImages += 1 - else: - self.noVideos += 1 - - - def gio_scan(path, fileSizeSum): - """recursive function to scan a directory and its subdirectories - for photos and possibly videos""" - - children = path.enumerate_children('standard::name,standard::type,standard::size,time::modified') - - for child in children: - if not self.running: - self.lock.acquire() - self.running = True - - if not self.ctrl: - return None - - if child.get_file_type() == gio.FILE_TYPE_DIRECTORY: - fileSizeSum = gio_scan(path.get_child(child.get_name()), fileSizeSum) - if fileSizeSum == None: - # this value will be None only if the thread is exiting - return None - elif child.get_file_type() == gio.FILE_TYPE_REGULAR: - name = child.get_name() - download, isImage, isVideo = downloadable(name) - if download: - size = child.get_size() - modificationTime = child.get_modification_time() - addFile(name, path.get_path(), size, modificationTime, self.cardMedia.prettyName(limit=0), self.cardMedia.volume, isImage) - fileSizeSum += size - - return fileSizeSum - - - imagesAndVideos = [] - fileSizeSum = 0 - self.noVideos = 0 - self.noImages = 0 - - if not using_gio or not self.cardMedia.volume: - 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: - return None - - - download, isImage, isVideo = downloadable(name) - if download: - fullFileName = os.path.join(root, name) - size = os.path.getsize(fullFileName) - modificationTime = os.path.getmtime(fullFileName) - addFile(name, root, size, modificationTime, self.cardMedia.prettyName(limit=0), self.cardMedia.volume, isImage) - fileSizeSum += size - - - else: - # using gio and have a volume - # make call to recursive function to scan volume - fileSizeSum = gio_scan(self.cardMedia.volume.volume.get_root(), fileSizeSum) - if fileSizeSum == None: - # thread exiting - return None - - # sort in place based on modification time - imagesAndVideos.sort(key=operator.itemgetter(1)) - noFiles = len(imagesAndVideos) - - self.scanComplete = True - - self.display_file_types = file_types_by_number(self.noImages, self.noVideos) - - - if noFiles: - self.cardMedia.setMedia(imagesAndVideos, fileSizeSum, noFiles) - # 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 photos that can be copied. For example, the user might see the following: - # '0 of 512 photos' or '0 of 10 videos' or '0 of 202 photos and videos'. - # This particular text is displayed to the user before the download has started. - display = _("%(number)s %(filetypes)s") % {'number':noFiles, 'filetypes':self.display_file_types} - display_queue.put((media_collection_treeview.updateCard, (self.thread_id, self.cardMedia.sizeOfImagesAndVideos()))) - display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, 0.0, display, 0))) - 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 photos 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 %(filetypes)s on %(device)s") % - {'number': noFiles, 'filetypes':self.display_file_types, - '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 %(filetypes)s found on %(device)s") % {'device':self.cardMedia.prettyName(limit=0), 'filetypes':self.types_searched_for}) - return False - - - 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 notifyAndUnmount(umountAttemptOK): - if not self.cardMedia.volume: - unmountMessage = "" - notificationName = PROGRAM_NAME - else: - notificationName = self.cardMedia.volume.get_name() - if self.prefs.auto_unmount and umountAttemptOK: - 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 = "" - - file_types = file_types_by_number(noImagesDownloaded, noVideosDownloaded) - file_types_skipped = file_types_by_number(noImagesSkipped, noVideosSkipped) - message = _("%(noFiles)s %(filetypes)s downloaded") % {'noFiles':noFilesDownloaded, 'filetypes': file_types} - noFilesSkipped = noImagesSkipped + noVideosSkipped - if noFilesSkipped: - message += "\n" + _("%(noFiles)s %(filetypes)s failed to download") % {'noFiles':noFilesSkipped, 'filetypes':file_types_skipped} - - if self.noWarnings: - message = "%s\n%s " % (message, self.noWarnings) + _("warnings") - if self.noErrors: - message = "%s\n%s " % (message, self.noErrors) + _("errors") - - if unmountMessage: - message = "%s\n%s" % (message, unmountMessage) - - n = pynotify.Notification(notificationName, message) - - if self.cardMedia.volume: - icon = self.cardMedia.volume.get_icon_pixbuf(self.parentApp.notification_icon_size) - else: - icon = self.parentApp.application_icon - - n.set_icon_from_pixbuf(icon) - n.show() - - def createTempDir(baseDir): - """ - Create a temporary directory in which to download the photos to. - - Returns the directory if it was created, else returns None. - - 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 actual download folder will be slow!""" - try: - t = tempfile.mkdtemp(prefix='rapid-tmp-', - dir=baseDir) - return t - except OSError, (errno, strerror): - if not self.cardMedia.volume: - image_device = _("Source: %s\n") % self.cardMedia.getPath() - else: - _("Device: %s\n") % self.cardMedia.volume.get_name() - destination = _("Destination: %s") % baseDir - logError(config.CRITICAL_ERROR, _('Could not create temporary download directory'), - image_device + destination, - _("Download cannot proceed")) - cmd_line(_("Error:") + " " + _('Could not create temporary download directory')) - cmd_line(image_device + destination) - cmd_line(_("Download cannot proceed")) - display_queue.put((media_collection_treeview.removeCard, (self.thread_id, ))) - display_queue.put((self.parentApp.downloadFailed, (self.thread_id, ))) - display_queue.close("rw") - self.running = False - self.lock.release() - return None - - def setupBackup(): - """ - Check for presence of backup path or volumes, and return the number of devices being used (1 in case of a path) - """ - no_devices = 0 - if self.prefs.backup_images: - no_devices = len(self.parentApp.backupVolumes) - if not self.prefs.backup_device_autodetection: - if not os.path.isdir(self.prefs.backup_location): - # the user has manually specified a path, but it - # does not exist. This is a problem. - try: - os.makedirs(self.prefs.backup_location) - except: - logError(config.SERIOUS_ERROR, _("Backup path does not exist"), - _("The path %s could not be created") % path, - _("No backups can occur") - ) - no_devices = 0 - return no_devices - - def checkIfNeedAJobCode(): - needAJobCode = NeedAJobCode(self.prefs) - - for f in self.cardMedia.imagesAndVideos: - mediaFile = f[0] - if mediaFile.status in [STATUS_WARNING, STATUS_NOT_DOWNLOADED]: - if needAJobCode.needAJobCode(mediaFile.jobcode, mediaFile.isImage): - return True - return False - - def createBothTempDirs(): - self.photoTempWorkingDir = createTempDir(photoBaseDownloadDir) - created = self.photoTempWorkingDir is not None - if created and DOWNLOAD_VIDEO: - self.videoTempWorkingDir = createTempDir(videoBaseDownloadDir) - created = self.videoTempWorkingDir is not None - - return created - - - def checkProblemWithNameGeneration(mediaFile): - if mediaFile.problem.has_problem(): - logError(config.WARNING, - mediaFile.problem.get_title(), - _("Source: %(source)s\nDestination: %(destination)s\n%(problem)s") % - {'source': mediaFile.fullFileName, 'destination': mediaFile.downloadFullFileName, 'problem': mediaFile.problem.get_problems()}) - mediaFile.status = STATUS_DOWNLOADED_WITH_WARNING - - def fileAlreadyExists(mediaFile, identifier=None): - """ Notify the user that the photo or video could not be downloaded because it already exists""" - - # get information on when the existing file was last modified - try: - modificationTime = os.path.getmtime(mediaFile.downloadFullFileName) - dt = datetime.datetime.fromtimestamp(modificationTime) - date = dt.strftime("%x") - time = dt.strftime("%X") - except: - sys.stderr.write("WARNING: could not determine the file modification time of an existing file\n") - date = time = '' - - if not identifier: - mediaFile.problem.add_problem(None, pn.FILE_ALREADY_EXISTS_NO_DOWNLOAD, {'filetype':mediaFile.displayNameCap}) - mediaFile.problem.add_extra_detail(pn.EXISTING_FILE, {'filetype': mediaFile.displayName, 'date': date, 'time': time}) - mediaFile.status = STATUS_DOWNLOAD_FAILED - log_status = config.SERIOUS_ERROR - problem_text = pn.extra_detail_definitions[pn.EXISTING_FILE] % {'date':date, 'time':time, 'filetype': mediaFile.displayName} - else: - mediaFile.problem.add_problem(None, pn.UNIQUE_IDENTIFIER_ADDED, {'filetype':mediaFile.displayNameCap}) - mediaFile.problem.add_extra_detail(pn.UNIQUE_IDENTIFIER, {'identifier': identifier, 'filetype': mediaFile.displayName, 'date': date, 'time': time}) - mediaFile.status = STATUS_DOWNLOADED_WITH_WARNING - log_status = config.WARNING - problem_text = pn.extra_detail_definitions[pn.UNIQUE_IDENTIFIER] % {'identifier': identifier, 'filetype': mediaFile.displayName, 'date': date, 'time': time} - - logError(log_status, mediaFile.problem.get_title(), - _("Source: %(source)s\nDestination: %(destination)s") - % {'source': mediaFile.fullFileName, 'destination': mediaFile.downloadFullFileName}, - problem_text) - - def downloadCopyingError(mediaFile, inst=None, errno=None, strerror=None): - """Notify the user that an error occurred (most likely at the OS / filesystem level) when coyping a photo or video""" - - if errno != None and strerror != None: - mediaFile.problem.add_problem(None, pn.DOWNLOAD_COPYING_ERROR_W_NO, {'filetype': mediaFile.displayName}) - mediaFile.problem.add_extra_detail(pn.DOWNLOAD_COPYING_ERROR_W_NO_DETAIL, {'errorno': errno, 'strerror': strerror}) - - else: - mediaFile.problem.add_problem(None, pn.DOWNLOAD_COPYING_ERROR, {'filetype': mediaFile.displayName}) - if not inst: - # hopefully inst will never be None, but just to be safe... - inst = _("Please check your system and try again.") - mediaFile.problem.add_extra_detail(pn.DOWNLOAD_COPYING_ERROR_DETAIL, inst) - - logError(config.SERIOUS_ERROR, mediaFile.problem.get_title(), mediaFile.problem.get_problems()) - mediaFile.status = STATUS_DOWNLOAD_FAILED - - def sameNameDifferentExif(image_name, mediaFile): - """Notify the user that a file was already downloaded with the same name, but the exif information was different""" - i1_ext, i1_date_time, i1_subseconds = downloaded_files.extExifDateTime(image_name) - detail = {'image1': "%s%s" % (image_name, i1_ext), - 'image1_date': i1_date_time.strftime("%x"), - 'image1_time': time_subseconds_human_readable(i1_date_time, i1_subseconds), - 'image2': mediaFile.name, - 'image2_date': mediaFile.metadata.dateTime().strftime("%x"), - 'image2_time': time_subseconds_human_readable( - mediaFile.metadata.dateTime(), - mediaFile.metadata.subSeconds())} - mediaFile.problem.add_problem(None, pn.SAME_FILE_DIFFERENT_EXIF, detail) - - msg = pn.problem_definitions[pn.SAME_FILE_DIFFERENT_EXIF][1] % detail - logError(config.WARNING,_('Photos detected with the same filenames, but taken at different times'), msg) - mediaFile.status = STATUS_DOWNLOADED_WITH_WARNING - - def generateSubfolderAndFileName(mediaFile): - """ - Generates subfolder and file names for photos and videos - """ - - skipFile = alreadyDownloaded = False - sequence_to_use = None - - if mediaFile.isVideo: - fileRenameFactory = self.videoRenamePrefsFactory - subfolderFactory = self.videoSubfolderPrefsFactory - else: - # file is an photo - fileRenameFactory = self.imageRenamePrefsFactory - subfolderFactory = self.subfolderPrefsFactory - - fileRenameFactory.setJobCode(mediaFile.jobcode) - subfolderFactory.setJobCode(mediaFile.jobcode) - - mediaFile.problem = pn.Problem() - subfolderFactory.initializeProblem(mediaFile.problem) - fileRenameFactory.initializeProblem(mediaFile.problem) - - # Here we cannot assume that the subfolder value will contain something -- the user may have changed the preferences after the scan - mediaFile.downloadSubfolder = subfolderFactory.generateNameUsingPreferences( - mediaFile.metadata, mediaFile.name, - self.stripCharacters, fallback_date = mediaFile.modificationTime) - - - if self.prefs.synchronize_raw_jpg and usesImageSequenceElements and mediaFile.isImage: - #synchronizing RAW and JPEG only applies to photos, not videos - image_name, image_ext = os.path.splitext(mediaFile.name) - with self.downloadedFilesLock: - i, sequence_to_use = downloaded_files.matching_pair(image_name, image_ext, mediaFile.metadata.dateTime(), mediaFile.metadata.subSeconds()) - if i == -1: - # this exact file has already been downloaded (same extension, same filename, and same exif date time subsecond info) - if not addUniqueIdentifier: - logError(config.SERIOUS_ERROR,_('Photo has already been downloaded'), - _("Source: %(source)s") % {'source': mediaFile.fullFileName}) - mediaFile.problem.add_problem(None, pn.FILE_ALREADY_DOWNLOADED, {'filetype': mediaFile.displayNameCap}) - skipFile = True - - - # pass the subfolder the image will go into, as this is needed to determine subfolder sequence numbers - # indicate that sequences chosen should be queued - - if not skipFile: - mediaFile.downloadName = fileRenameFactory.generateNameUsingPreferences( - mediaFile.metadata, mediaFile.name, self.stripCharacters, mediaFile.downloadSubfolder, - sequencesPreliminary = True, - sequence_to_use = sequence_to_use, - fallback_date = mediaFile.modificationTime) - - mediaFile.downloadPath = os.path.join(mediaFile.downloadFolder, mediaFile.downloadSubfolder) - mediaFile.downloadFullFileName = os.path.join(mediaFile.downloadPath, mediaFile.downloadName) - - if not mediaFile.downloadName or not mediaFile.downloadSubfolder: - if not mediaFile.downloadName and not mediaFile.downloadSubfolder: - area = _("subfolder and filename") - elif not mediaFile.downloadName: - area = _("filename") - else: - area = _("subfolder") - problem.add_problem(None, pn.ERROR_IN_NAME_GENERATION, {'filetype': mediaFile.displayNameCap, 'area': area}) - problem.add_extra_detail(pn.NO_DATA_TO_NAME, {'filetype': area}) - skipFile = True - logError(config.SERIOUS_ERROR, pn.problem_definitions[ERROR_IN_NAME_GENERATION][1] % {'filetype': mediaFile.displayNameCap, 'area': area}) - - if not skipFile: - checkProblemWithNameGeneration(mediaFile) - else: - self.sizeDownloaded += mediaFile.size * (no_backup_devices + 1) - mediaFile.status = STATUS_DOWNLOAD_FAILED - - return (skipFile, sequence_to_use) - - def progress_callback(amount_downloaded, total): - if (amount_downloaded - self.bytes_downloaded > 2097152) or (amount_downloaded == total): - chunk_downloaded = amount_downloaded - self.bytes_downloaded - self.bytes_downloaded = amount_downloaded - percentComplete = (float(self.sizeDownloaded + amount_downloaded) / sizeFiles) * 100 - - display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, percentComplete, None, chunk_downloaded))) - - def downloadFile(mediaFile, sequence_to_use): - """ - Downloads the photo or video file to the specified subfolder - """ - - if not mediaFile.isImage: - renameFactory = self.videoRenamePrefsFactory - else: - renameFactory = self.imageRenamePrefsFactory - - def progress_callback_no_update(amount_downloaded, total): - pass - - try: - fileDownloaded = False - if not os.path.isdir(mediaFile.downloadPath): - os.makedirs(mediaFile.downloadPath) - - nameUniqueBeforeCopy = True - downloadNonUniqueFile = True - - # do a preliminary check to see if a file with the same name already exists - if os.path.exists(mediaFile.downloadFullFileName): - nameUniqueBeforeCopy = False - if not addUniqueIdentifier: - downloadNonUniqueFile = False - if (usesVideoSequenceElements and not mediaFile.isImage) or (usesImageSequenceElements and mediaFile.isImage and not self.prefs.synchronize_raw_jpg): - # potentially, a unique file name could still be generated - # investigate this possibility - with self.fileSequenceLock: - for possibleName in renameFactory.generateNameSequencePossibilities( - mediaFile.metadata, - mediaFile.name, self.stripCharacters, mediaFile.downloadSubfolder, - fallback_date = mediaFile.modificationTime): - if possibleName: - # no need to check for any problems here, it's just a temporary name - possibleFile = os.path.join(mediaFile.downloadPath, possibleName) - possibleTempFile = os.path.join(tempWorkingDir, possibleName) - if not os.path.exists(possibleFile) and not os.path.exists(possibleTempFile): - downloadNonUniqueFile = True - break - - - if not downloadNonUniqueFile: - fileAlreadyExists(mediaFile) - - copy_succeeded = False - if nameUniqueBeforeCopy or downloadNonUniqueFile: - tempWorkingfile = os.path.join(tempWorkingDir, mediaFile.downloadName) - if using_gio: - g_dest = gio.File(path=tempWorkingfile) - g_src = gio.File(path=mediaFile.fullFileName) - try: - if not g_src.copy(g_dest, progress_callback, cancellable=gio.Cancellable()): - downloadCopyingError(mediaFile) - else: - copy_succeeded = True - except glib.GError, inst: - downloadCopyingError(mediaFile, inst=inst) - else: - shutil.copy2(mediaFile.fullFileName, tempWorkingfile) - copy_succeeded = True - - if copy_succeeded: - with self.fileRenameLock: - doRename = True - if usesSequenceElements: - with self.fileSequenceLock: - # get a filename and use this as the "real" filename - if sequence_to_use is None and self.prefs.synchronize_raw_jpg and mediaFile.isImage: - # must check again, just in case the matching pair has been downloaded in the meantime - image_name, image_ext = os.path.splitext(mediaFile.name) - with self.downloadedFilesLock: - i, sequence_to_use = downloaded_files.matching_pair(image_name, image_ext, mediaFile.metadata.dateTime(), mediaFile.metadata.subSeconds()) - if i == -99: - sameNameDifferentExif(image_name, mediaFile) - - mediaFile.downloadName = renameFactory.generateNameUsingPreferences( - mediaFile.metadata, mediaFile.name, self.stripCharacters, mediaFile.downloadSubfolder, - sequencesPreliminary = False, - sequence_to_use = sequence_to_use, - fallback_date = mediaFile.modificationTime) - - if not mediaFile.downloadName: - # there was a serious error generating the filename - doRename = False - else: - mediaFile.downloadFullFileName = os.path.join(mediaFile.downloadPath, mediaFile.downloadName) - # check if the file exists again - if os.path.exists(mediaFile.downloadFullFileName): - if not addUniqueIdentifier: - doRename = False - fileAlreadyExists(mediaFile) - else: - # add basic suffix to make the filename unique - name = os.path.splitext(mediaFile.downloadName) - suffixAlreadyUsed = True - while suffixAlreadyUsed: - if mediaFile.downloadFullFileName in duplicate_files: - duplicate_files[mediaFile.downloadFullFileName] += 1 - else: - duplicate_files[mediaFile.downloadFullFileName] = 1 - identifier = '_%s' % duplicate_files[mediaFile.downloadFullFileName] - mediaFile.downloadName = name[0] + identifier + name[1] - possibleNewFile = os.path.join(mediaFile.downloadPath, mediaFile.downloadName) - suffixAlreadyUsed = os.path.exists(possibleNewFile) - - fileAlreadyExists(mediaFile, identifier) - mediaFile.downloadFullFileName = possibleNewFile - - - if doRename: - rename_succeeded = False - if using_gio: - g_dest = gio.File(path=mediaFile.downloadFullFileName) - g_src = gio.File(path=tempWorkingfile) - try: - if not g_src.move(g_dest, progress_callback_no_update, cancellable=gio.Cancellable()): - downloadCopyingError(mediaFile) - else: - rename_succeeded = True - except glib.GError, inst: - downloadCopyingError(mediaFile, inst=inst) - else: - os.rename(tempWorkingfile, mediaFile.downloadFullFileName) - rename_succeeded = True - - if rename_succeeded: - fileDownloaded = True - if mediaFile.status != STATUS_DOWNLOADED_WITH_WARNING: - mediaFile.status = STATUS_DOWNLOADED - if usesImageSequenceElements: - if self.prefs.synchronize_raw_jpg and mediaFile.isImage: - name, ext = os.path.splitext(mediaFile.name) - if sequence_to_use is None: - with self.fileSequenceLock: - seq = renameFactory.sequences.getFinalSequence() - else: - seq = sequence_to_use - with self.downloadedFilesLock: - downloaded_files.add_download(name, ext, mediaFile.metadata.dateTime(), mediaFile.metadata.subSeconds(), seq) - - - with self.fileSequenceLock: - if sequence_to_use is None: - renameFactory.sequences.imageCopySucceeded() - if usesStoredSequenceNo: - self.prefs.stored_sequence_no += 1 - - with self.fileSequenceLock: - if sequence_to_use is None: - 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, OSError), (errno, strerror): - downloadCopyingError(mediaFile, errno=errno, strerror=strerror) - - if usesSequenceElements: - if not fileDownloaded and sequence_to_use is None: - renameFactory.sequences.imageCopyFailed() - - #update record keeping using in tracking progress - self.sizeDownloaded += mediaFile.size - self.bytes_downloaded_in_download = self.bytes_downloaded - - return fileDownloaded - - - def backupFile(mediaFile, fileDownloaded, no_backup_devices): - """ - Backup photo or video to path(s) chosen by the user - - there are three scenarios: - (1) file has just been downloaded and should now be backed up - (2) file was already downloaded on some previous occassion and should still be backed up, because it hasn't been yet - (3) file has been backed up already (or at least, a file with the same name already exists) - - A backup medium can be used to backup photos or videos, or both. - """ - - backed_up = False - fileNotBackedUpMessageDisplayed = False - error_encountered = False - expected_bytes_downloaded = self.sizeDownloaded + no_backup_devices * mediaFile.size - - if no_backup_devices: - for rootBackupDir in self.parentApp.backupVolumes: - self.bytes_downloaded = 0 - if self.prefs.backup_device_autodetection: - volume = self.parentApp.backupVolumes[rootBackupDir].get_name() - if mediaFile.isImage: - backupDir = os.path.join(rootBackupDir, self.prefs.backup_identifier) - else: - backupDir = os.path.join(rootBackupDir, self.prefs.video_backup_identifier) - else: - # photos and videos will be backed up into the same root folder, which the user has manually specified - backupDir = rootBackupDir - volume = backupDir # os.path.split(backupDir)[1] - - # if user has chosen auto detection, then: - # photos should only be backed up to photo backup locations - # videos should only be backed up to video backup locations - # if user did not choose autodetection, and the backup path doesn't exist, then - # will try to create it - if os.path.isdir(backupDir) or not self.prefs.backup_device_autodetection: - - backupPath = os.path.join(backupDir, mediaFile.downloadSubfolder) - newBackupFile = os.path.join(backupPath, mediaFile.downloadName) - copyBackup = True - if os.path.exists(newBackupFile): - # this check is of course not thread safe -- it doesn't need to be, because at this stage the file names are going to be unique - # (the folder structure is the same as the actual download folders, and the file names are unique in them) - copyBackup = self.prefs.backup_duplicate_overwrite - - if copyBackup: - mediaFile.problem.add_problem(None, pn.BACKUP_EXISTS_OVERWRITTEN, volume) - else: - mediaFile.problem.add_problem(None, pn.BACKUP_EXISTS, volume) - severity = config.SERIOUS_ERROR - fileNotBackedUpMessageDisplayed = True - - title = _("Backup of %(file_type)s already exists") % {'file_type': mediaFile.displayName} - details = _("Source: %(source)s\nDestination: %(destination)s") \ - % {'source': mediaFile.fullFileName, 'destination': newBackupFile} - if copyBackup: - resolution = _("Backup %(file_type)s overwritten") % {'file_type': mediaFile.displayName} - else: - if self.prefs.backup_device_autodetection: - volume = self.parentApp.backupVolumes[rootBackupDir].get_name() - resolution = _("%(file_type)s not backed up to %(volume)s") % {'file_type': mediaFile.displayNameCap, 'volume': volume} - else: - resolution = _("%(file_type)s not backed up") % {'file_type': mediaFile.displayNameCap} - logError(severity, title, details, resolution) - - if copyBackup: - if fileDownloaded: - fileToCopy = mediaFile.downloadFullFileName - else: - fileToCopy = mediaFile.fullFileName - if os.path.isdir(backupPath): - pathExists = True - else: - pathExists = False - # create the backup subfolders - if using_gio: - dirs = gio.File(backupPath) - try: - if dirs.make_directory_with_parents(cancellable=gio.Cancellable()): - pathExists = True - except glib.GError, inst: - fileNotBackedUpMessageDisplayed = True - mediaFile.problem.add_problem(None, pn.BACKUP_DIRECTORY_CREATION, volume) - mediaFile.problem.add_extra_detail('%s%s' % (pn.BACKUP_DIRECTORY_CREATION, volume), inst) - error_encountered = True - logError(config.SERIOUS_ERROR, _('Backing up error'), - _("Destination directory could not be created: %(directory)s\n") % - {'directory': backupPath, } + - _("Source: %(source)s\nDestination: %(destination)s") % - {'source': mediaFile.fullFileName, 'destination': newBackupFile} + "\n" + - _("Error: %(inst)s") % {'inst': inst}, - _('The %(file_type)s was not backed up.') % {'file_type': mediaFile.displayName} - ) - else: - # recreate folder structure in backup location - # cannot do os.makedirs(backupPath) - it can give bad results when using external drives - # we know backupDir exists - # all the components of subfolder may not - folders = mediaFile.downloadSubfolder.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) - pathExists = True - except (IOError, OSError), (errno, strerror): - fileNotBackedUpMessageDisplayed = True - inst = "%s: %s" % (errno, strerror) - mediaFile.problem.add_problem(None, pn.BACKUP_DIRECTORY_CREATION, volume) - mediaFile.problem.add_extra_detail('%s%s' % (pn.BACKUP_DIRECTORY_CREATION, volume), inst) - error_encountered = True - logError(config.SERIOUS_ERROR, _('Backing up error'), - _("Destination directory could not be created: %(directory)s\n") % - {'directory': backupPath, } + - _("Source: %(source)s\nDestination: %(destination)s") % - {'source': mediaFile.fullFileName, 'destination': newBackupFile} + "\n" + - _("Error: %(errno)s %(strerror)s") % {'errno': errno, 'strerror': strerror}, - _('The %(file_type)s was not backed up.') % {'file_type': mediaFile.displayName} - ) - - break - - if pathExists: - if using_gio: - g_dest = gio.File(path=newBackupFile) - g_src = gio.File(path=fileToCopy) - if self.prefs.backup_duplicate_overwrite: - flags = gio.FILE_COPY_OVERWRITE - else: - flags = gio.FILE_COPY_NONE - try: - if not g_src.copy(g_dest, progress_callback, flags, cancellable=gio.Cancellable()): - fileNotBackedUpMessageDisplayed = True - mediaFile.problem.add_problem(None, pn.BACKUP_ERROR, volume) - error_encountered = True - else: - backed_up = True - if mediaFile.status == STATUS_DOWNLOAD_FAILED: - mediaFile.problem.add_problem(None, pn.NO_DOWNLOAD_WAS_BACKED_UP, volume) - except glib.GError, inst: - fileNotBackedUpMessageDisplayed = True - mediaFile.problem.add_problem(None, pn.BACKUP_ERROR, volume) - mediaFile.problem.add_extra_detail('%s%s' % (pn.BACKUP_ERROR, volume), inst) - error_encountered = True - logError(config.SERIOUS_ERROR, _('Backing up error'), - _("Source: %(source)s\nDestination: %(destination)s") % - {'source': fileToCopy, 'destination': newBackupFile} + "\n" + - _("Error: %(inst)s") % {'inst': inst}, - _('The %(file_type)s was not backed up.') % {'file_type': mediaFile.displayName} - ) - else: - try: - shutil.copy2(fileToCopy, newBackupFile) - backed_up = True - if mediaFile.status == STATUS_DOWNLOAD_FAILED: - mediaFile.problem.add_problem(None, pn.NO_DOWNLOAD_WAS_BACKED_UP, volume) - - except (IOError, OSError), (errno, strerror): - fileNotBackedUpMessageDisplayed = True - mediaFile.problem.add_problem(None, pn.BACKUP_ERROR, volume) - inst = "%s: %s" % (errno, strerror) - mediaFile.problem.add_extra_detail('%s%s' % (pn.BACKUP_ERROR, volume), inst) - error_encountered = True - logError(config.SERIOUS_ERROR, _('Backing up error'), - _("Source: %(source)s\nDestination: %(destination)s") % - {'source': fileToCopy, 'destination': newBackupFile} + "\n" + - _("Error: %(errno)s %(strerror)s") % {'errno': errno, 'strerror': strerror}, - _('The %(file_type)s was not backed up.') % {'file_type': mediaFile.displayName} - ) - - #update record keeping using in tracking progress - self.sizeDownloaded += mediaFile.size - self.bytes_downloaded_in_backup += self.bytes_downloaded - - if not backed_up and not fileNotBackedUpMessageDisplayed: - # The file has not been backed up to any medium - mediaFile.problem.add_problem(None, pn.NO_BACKUP_PERFORMED, {'filetype': mediaFile.displayNameCap}) - - severity = config.SERIOUS_ERROR - problem = _("%(file_type)s could not be backed up") % {'file_type': mediaFile.displayName} - details = _("Source: %(source)s") % {'source': mediaFile.fullFileName} - if self.prefs.backup_device_autodetection: - resolution = _("No suitable backup volume was found") - else: - resolution = _("A backup location was not found") - logError(severity, problem, details, resolution) - - if backed_up and mediaFile.status == STATUS_DOWNLOAD_FAILED: - mediaFile.problem.add_extra_detail(pn.BACKUP_OK_TYPE, mediaFile.displayNameCap) - - if not backed_up: - if mediaFile.status == STATUS_DOWNLOAD_FAILED: - mediaFile.status = STATUS_DOWNLOAD_AND_BACKUP_FAILED - else: - mediaFile.status = STATUS_BACKUP_PROBLEM - elif error_encountered: - # it was backed up to at least one volume, but there was an error on another backup volume - if mediaFile.status != STATUS_DOWNLOAD_FAILED: - mediaFile.status = STATUS_BACKUP_PROBLEM - - # Take into account instances where a backup device has been removed part way through a download - # (thereby making self.parentApp.backupVolumes have less items than expected) - if self.sizeDownloaded < expected_bytes_downloaded: - self.sizeDownloaded = expected_bytes_downloaded - return backed_up - - - self.hasStarted = True - display_queue.open('w') - - #Do not try to handle any preference errors here - getPrefs(False) - - #Check photo and video download path, create if necessary - photoBaseDownloadDir = self.prefs.download_folder - if not checkDownloadPath(photoBaseDownloadDir): - return # cleanup already done - - if DOWNLOAD_VIDEO: - videoBaseDownloadDir = self.prefs.video_download_folder - if not checkDownloadPath(videoBaseDownloadDir): - return - else: - videoBaseDownloadDir = self.videoTempWorkingDir = None - - if not createBothTempDirs(): - return - - s = scanMedia() - if s is None: - if not self.ctrl: - self.running = False - display_queue.put((media_collection_treeview.removeCard, (self.thread_id, ))) - display_queue.close("rw") - return - else: - sys.stderr.write("FIXME: scan returned None, but the thread is not meant to be exiting\n") - if not s: - cmd_line(_("This device has no %(types_searched_for)s to download from.") % {'types_searched_for': self.types_searched_for}) - display_queue.put((self.parentApp.downloadFailed, (self.thread_id, ))) - display_queue.close("rw") - self.running = False - return - - if self.scanResultsStale or self.scanResultsStaleDownloadFolder: - display_queue.put((self.parentApp.regenerateScannedDevices, (self.thread_id, ))) - all_files_downloaded = False - - totalNonErrorFiles = self.cardMedia.numberOfFilesNotCannotDownload() - - if not self.autoStart: - # halt thread, waiting to be restarted so download proceeds - self.cleanUp() - 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 createBothTempDirs(): - return - - else: - if need_job_code_for_renaming: - if checkIfNeedAJobCode(): - if job_code == None: - self.cleanUp() - self.waitingForJobCode = True - display_queue.put((self.parentApp.getJobCode, ())) - self.running = False - self.lock.acquire() - - if not self.ctrl: - # thread is exiting - display_queue.close("rw") - return - - self.running = True - self.waitingForJobCode = False - if not createBothTempDirs(): - return - else: - # User has entered a job code, and it's in the global variable - # Assign it to all those files that do not have one - display_queue.put((self.parentApp.selection_vbox.selection_treeview.apply_job_code, (job_code, False, True, self.thread_id))) - - # auto start could be false if the user hit cancel when prompted for a job code - if self.autoStart: - # set all in this thread to download pending - display_queue.put((self.parentApp.selection_vbox.selection_treeview.set_status_to_download_pending, (False, self.thread_id))) - # wait until all the files have had their status set to download pending, and once that is done, restart - self.running = False - self.lock.acquire() - self.running = True - - # set download started time - display_queue.put((self.parentApp.setDownloadStartTime, ())) - - while not all_files_downloaded: - - # set the download start time to be the time that the user clicked the download button, or if on auto start, the value just set - i = 0 - while self.parentApp.download_start_time is None or i > 2: - time.sleep(0.5) - i += 1 - - if self.parentApp.download_start_time: - start_time = self.parentApp.download_start_time - else: - # in a bizarre corner case situation, with mulitple cards of greatly varying size, - # it's possible the start time was set above and then in the meantime unset (very unlikely, but conceivably it could happen) - # fall back to the current time in this less than satisfactory situation - start_time = datetime.datetime.now() - - self.imageRenamePrefsFactory.setDownloadStartTime(start_time) - self.subfolderPrefsFactory.setDownloadStartTime(start_time) - if DOWNLOAD_VIDEO: - self.videoRenamePrefsFactory.setDownloadStartTime(start_time) - self.videoSubfolderPrefsFactory.setDownloadStartTime(start_time) - - self.noErrors = self.noWarnings = 0 - - 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)) - - - noFiles, sizeFiles, fileIndex = self.cardMedia.sizeAndNumberDownloadPending() - cmd_line(_("Attempting to download %s files") % noFiles) - - no_backup_devices = setupBackup() - - # include the time it takes to copy to the backup volumes - sizeFiles = sizeFiles * (no_backup_devices + 1) - - display_queue.put((self.parentApp.timeRemaining.set, (self.thread_id, sizeFiles))) - - i = 0 - self.sizeDownloaded = noFilesDownloaded = noImagesDownloaded = noVideosDownloaded = noImagesSkipped = noVideosSkipped = 0 - filesDownloadedSuccessfully = [] - self.bytes_downloaded_in_backup = 0 - - display_queue.put((self.parentApp.addToTotalDownloadSize, (sizeFiles, ))) - display_queue.put((self.parentApp.setOverallDownloadMark, ())) - display_queue.put((self.parentApp.postStartDownloadTasks, ())) - - sizeFiles = float(sizeFiles) - - addUniqueIdentifier = self.prefs.download_conflict_resolution == config.ADD_UNIQUE_IDENTIFIER - usesImageSequenceElements = self.imageRenamePrefsFactory.usesSequenceElements() - usesVideoSequenceElements = self.videoRenamePrefsFactory.usesSequenceElements() - usesSequenceElements = usesVideoSequenceElements or usesImageSequenceElements - - usesStoredSequenceNo = (self.imageRenamePrefsFactory.usesTheSequenceElement(rn.STORED_SEQ_NUMBER) or - self.videoRenamePrefsFactory.usesTheSequenceElement(rn.STORED_SEQ_NUMBER)) - sequences.setUseOfSequenceElements( - self.imageRenamePrefsFactory.usesTheSequenceElement(rn.SESSION_SEQ_NUMBER), - self.imageRenamePrefsFactory.usesTheSequenceElement(rn.SEQUENCE_LETTER)) - - # reset the progress bar to update the status of this download attempt - progressBarText = _("%(number)s of %(total)s %(filetypes)s") % {'number': 0, 'total': noFiles, 'filetypes':self.display_file_types} - display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, 0.0, progressBarText, 0))) - - - while i < noFiles: - # if the user pauses the download, then this will be triggered - if not self.running: - self.lock.acquire() - self.running = True - - if not self.ctrl: - self.running = False - self.cleanUp() - display_queue.close("rw") - return - - # get information about the image to deduce image name and path - mediaFile = self.cardMedia.imagesAndVideos[fileIndex[i]][0] - if not mediaFile.status == STATUS_DOWNLOAD_PENDING: - sys.stderr.write("FIXME: Thread %s is trying to download a file that it should not be!!" % self.thread_id) - else: - self.bytes_downloaded_in_download = self.bytes_downloaded_in_backup = self.bytes_downloaded = 0 - if mediaFile.isImage: - tempWorkingDir = self.photoTempWorkingDir - baseDownloadDir = photoBaseDownloadDir - else: - tempWorkingDir = self.videoTempWorkingDir - baseDownloadDir = videoBaseDownloadDir - - skipFile, sequence_to_use = generateSubfolderAndFileName(mediaFile) - - if skipFile: - if mediaFile.isImage: - noImagesSkipped += 1 - else: - noVideosSkipped += 1 - else: - fileDownloaded = downloadFile(mediaFile, sequence_to_use) - - if self.prefs.backup_images: - backed_up = backupFile(mediaFile, fileDownloaded, no_backup_devices) - - if fileDownloaded: - noFilesDownloaded += 1 - if mediaFile.isImage: - noImagesDownloaded += 1 - else: - noVideosDownloaded += 1 - if self.prefs.backup_images and backed_up: - filesDownloadedSuccessfully.append(mediaFile.fullFileName) - elif not self.prefs.backup_images: - filesDownloadedSuccessfully.append(mediaFile.fullFileName) - else: - if mediaFile.isImage: - noImagesSkipped += 1 - else: - noVideosSkipped += 1 - - #update the selction treeview in the main window with the new status of the file - display_queue.put((self.parentApp.update_status_post_download, (mediaFile.treerowref, ))) - - percentComplete = (float(self.sizeDownloaded) / sizeFiles) * 100 - - if self.sizeDownloaded == sizeFiles and (totalNonErrorFiles - noFiles): - progressBarText = _("%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)") % { - 'number': i + 1, 'total': noFiles, 'filetypes':self.display_file_types, - 'remaining': totalNonErrorFiles - noFiles} - else: - progressBarText = _("%(number)s of %(total)s %(filetypes)s") % {'number': i + 1, 'total': noFiles, 'filetypes':self.display_file_types} - - if using_gio: - # do not want to update the progress bar any more than it has already been updated - size = mediaFile.size * (no_backup_devices + 1) - self.bytes_downloaded_in_download - self.bytes_downloaded_in_backup - else: - size = mediaFile.size * (no_backup_devices + 1) - display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, percentComplete, progressBarText, size))) - - i += 1 - - with self.statsLock: - self.downloadStats.adjust(self.sizeDownloaded, noImagesDownloaded, noVideosDownloaded, noImagesSkipped, noVideosSkipped, self.noWarnings, self.noErrors) - - if self.prefs.auto_delete: - j = 0 - for imageOrVideo in filesDownloadedSuccessfully: - try: - os.unlink(imageOrVideo) - j += 1 - except OSError, (errno, strerror): - logError(config.SERIOUS_ERROR, _("Could not delete photo or video from device"), - _("Photo: %(source)s\nError: %(errno)s %(strerror)s") - % {'source': image, 'errno': errno, 'strerror': strerror}) - except: - logError(config.SERIOUS_ERROR, _("Could not delete photo or video from device"), - _("Photo: %(source)s")) - - cmd_line(_("Deleted %(number)i %(filetypes)s from device") % {'number':j, 'filetypes':self.display_file_types}) - - totalNonErrorFiles = totalNonErrorFiles - noFiles - if totalNonErrorFiles == 0: - all_files_downloaded = True - - # must manually delete these variables, or else the media cannot be unmounted (bug in some versions of pyexiv2 / exiv2) - # for some reason directories on the device remain open with read only access, even after these steps - I don't know why - del self.subfolderPrefsFactory, self.imageRenamePrefsFactory, self.videoSubfolderPrefsFactory, self.videoRenamePrefsFactory - for i in self.cardMedia.imagesAndVideos: - i[0].metadata = None - - notifyAndUnmount(umountAttemptOK = all_files_downloaded) - cmd_line(_("Download complete from %s") % self.cardMedia.prettyName(limit=0)) - display_queue.put((self.parentApp.notifyUserAllDownloadsComplete,())) - display_queue.put((self.parentApp.resetSequences,())) - - if all_files_downloaded: - self.downloadComplete = True - else: - self.cleanUp() - self.downloadStarted = False - 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 createBothTempDirs(): - return - - - display_queue.put((self.parentApp.exitOnDownloadComplete, ())) - display_queue.close("rw") - - self.cleanUp() - - self.running = False - if noFiles: - 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(str(self.thread_id) + " thread error\n") - - def cleanUp(self): - """ - Deletes temporary files and folders - """ - - for tempWorkingDir in (self.videoTempWorkingDir, self.photoTempWorkingDir): - if tempWorkingDir: - # possibly delete any lingering files - if os.path.isdir(tempWorkingDir): - tf = os.listdir(tempWorkingDir) - if tf: - for f in tf: - os.remove(os.path.join(tempWorkingDir, f)) - os.rmdir(tempWorkingDir) - - 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) - """ - - # cleanup any temporary directories and files - self.cleanUp() - - 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 devices and associated copying progress. - - Assumes a threaded environment. - """ - def __init__(self, parentApp): - - self.parentApp = parentApp - # device name, size of images on the device (human readable), copy progress (%), copy text - self.liststore = gtk.ListStore(str, str, float, str) - self.mapThreadToRow = {} + self.parent_app = parent_app + # device icon & name, size of images on the device (human readable), + # copy progress (%), copy text, eject button (None if irrelevant), + # process id + self.liststore = gtk.ListStore(gtk.gdk.Pixbuf, str, str, float, str, + gtk.gdk.Pixbuf, int) + self.map_process_to_row = {} + self.devices_by_scan_pid = {} gtk.TreeView.__init__(self, self.liststore) @@ -3088,587 +143,430 @@ class MediaTreeView(gtk.TreeView): 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) + + # Device refers to a thing like a camera, memory card in its reader, + # external hard drive, Portable Storage Device, etc. + column0 = gtk.TreeViewColumn(_("Device")) + pixbuf_renderer = gtk.CellRendererPixbuf() + text_renderer = gtk.CellRendererText() + text_renderer.props.ellipsize = pango.ELLIPSIZE_MIDDLE + text_renderer.set_fixed_size(160, -1) + eject_renderer = gtk.CellRendererPixbuf() + column0.pack_start(pixbuf_renderer, expand=False) + column0.pack_start(text_renderer, expand=True) + column0.pack_end(eject_renderer, expand=False) + column0.add_attribute(pixbuf_renderer, 'pixbuf', 0) + column0.add_attribute(text_renderer, 'text', 1) + column0.add_attribute(eject_renderer, 'pixbuf', 5) 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) + + # Size refers to the total size of images on the device, typically in + # MB or GB + column1 = gtk.TreeViewColumn(_("Size"), gtk.CellRendererText(), text=2) self.append_column(column1) column2 = gtk.TreeViewColumn(_("Download Progress"), - gtk.CellRendererProgress(), value=2, text=3) + gtk.CellRendererProgress(), + value=3, + text=4) self.append_column(column2) self.show_all() - def addCard(self, thread_id, cardName, sizeFiles, progress = 0.0, progressBarText = ''): + icontheme = gtk.icon_theme_get_default() + try: + self.eject_pixbuf = icontheme.load_icon('media-eject', 16, + gtk.ICON_LOOKUP_USE_BUILTIN) + except: + self.eject_pixbuf = gtk.gdk.pixbuf_new_from_file( + paths.share_dir('glade3/media-eject.png')) + + self.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self.connect('button-press-event', self.button_clicked) + + + def add_device(self, process_id, device, progress_bar_text = ''): # add the row, and get a temporary pointer to the row - iter = self.liststore.append((cardName, sizeFiles, progress, progressBarText)) + size_files = '' + progress = 0.0 + + if device.mount is None: + eject = None + else: + eject = self.eject_pixbuf + + self.devices_by_scan_pid[process_id] = device + + iter = self.liststore.append((device.get_icon(), + device.get_name(), + size_files, + progress, + progress_bar_text, + eject, + process_id)) - self._setThreadMap(thread_id, iter) + self._set_process_map(process_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) + # please note, at program startup, self.row_height() 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 + # must account for header row at the top + row_height = self.get_background_area(0, self.get_column(0))[3] + 1 + height = (len(self.map_process_to_row) + 1) * row_height + self.parent_app.device_collection_scrolledwindow.set_size_request(-1, height) - def updateCard(self, thread_id, totalSizeFiles): + def update_device(self, process_id, total_size_files): """ Updates the size of the photos and videos on the device, displayed to the user """ - if thread_id in self.mapThreadToRow: - iter = self._getThreadMap(thread_id) - self.liststore.set_value(iter, 1, totalSizeFiles) + if process_id in self.map_process_to_row: + iter = self._get_process_map(process_id) + self.liststore.set_value(iter, 2, total_size_files) else: - sys.stderr.write("FIXME: this card is unknown") + logger.critical("This device is unknown") + + def get_device(self, process_id): + return self.devices_by_scan_pid.get(process_id) - def removeCard(self, thread_id): - if thread_id in self.mapThreadToRow: - iter = self._getThreadMap(thread_id) + def remove_device(self, process_id): + if process_id in self.map_process_to_row: + iter = self._get_process_map(process_id) self.liststore.remove(iter) - del self.mapThreadToRow[thread_id] + del self.map_process_to_row[process_id] + del self.devices_by_scan_pid[process_id] + + def get_all_displayed_processes(self): + """ + returns a list of the processes currently being displayed to the user + """ + return self.map_process_to_row.keys() - def _setThreadMap(self, thread_id, iter): + def _set_process_map(self, process_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 + treerowref = gtk.TreeRowReference(self.liststore, path) + self.map_process_to_row[process_id] = treerowref - def _getThreadMap(self, thread_id): + def _get_process_map(self, process_id): """ - return the tree iter for this thread + return the tree iter for this process """ - if thread_id in self.mapThreadToRow: - treerowRef = self.mapThreadToRow[thread_id] - path = treerowRef.get_path() + if process_id in self.map_process_to_row: + treerowref = self.map_process_to_row[process_id] + path = treerowref.get_path() iter = self.liststore.get_iter(path) return iter else: return None - def updateProgress(self, thread_id, percentComplete, progressBarText, bytesDownloaded): + def update_progress(self, scan_pid, percent_complete, progress_bar_text, bytes_downloaded): - iter = self._getThreadMap(thread_id) + iter = self._get_process_map(scan_pid) if iter: - self.liststore.set_value(iter, 2, percentComplete) - if progressBarText: - self.liststore.set_value(iter, 3, progressBarText) - if percentComplete or bytesDownloaded: - self.parentApp.updateOverallProgress(thread_id, bytesDownloaded, percentComplete) - + if percent_complete: + self.liststore.set_value(iter, 3, percent_complete) + if progress_bar_text: + self.liststore.set_value(iter, 4, progress_bar_text) + if percent_complete or bytes_downloaded: + pass + #~ logger.info("Implement update overall progress") - 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] + 1 + def button_clicked(self, widget, event): + """ + Look for left single click on eject button + """ + if event.button == 1: + if len (self.liststore): + x = int(event.x) + y = int(event.y) + path, column, cell_x, cell_y = self.get_path_at_pos(x, y) + if path is not None: + if column == self.get_column(0): + if cell_x >= column.get_width() - self.eject_pixbuf.get_width(): + iter = self.liststore.get_iter(path) + if self.liststore.get_value(iter, 5) is not None: + self.unmount(process_id = self.liststore.get_value(iter, 6)) + + def unmount(self, process_id): + device = self.devices_by_scan_pid[process_id] + if device.mount is not None: + logger.debug("Unmounting device with scan pid %s", process_id) + device.mount.unmount(self.unmount_callback) + + + def unmount_callback(self, mount, result): + name = mount.get_name() + try: + mount.unmount_finish(result) + logger.debug("%s successfully unmounted" % name) + except gio.Error, inst: + logger.error("%s did not unmount: %s", name, inst) + + title = _("%(device)s did not unmount") % {'device': name} + message = '%s' % inst + + n = pynotify.Notification(title, message) + n.set_icon_from_pixbuf(self.parent_app.application_icon) + n.show() + + +def create_cairo_image_surface(pil_image, image_width, image_height): + imgd = pil_image.tostring("raw","BGRA", 0, 1) + data = array.array('B',imgd) + stride = image_width * 4 + image = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32, + image_width, image_height, stride) + return image + +class ThumbnailCellRenderer(gtk.CellRenderer): + __gproperties__ = { + "image": (gobject.TYPE_PYOBJECT, "Image", + "Image", gobject.PARAM_READWRITE), + + "filename": (gobject.TYPE_STRING, "Filename", + "Filename", '', gobject.PARAM_READWRITE), + + "status": (gtk.gdk.Pixbuf, "Status", + "Status", gobject.PARAM_READWRITE), + } + + def __init__(self, checkbutton_height): + gtk.CellRenderer.__init__(self) + self.image = None + + self.image_area_size = 100 + self.text_area_size = 30 + self.padding = 6 + self.checkbutton_height = checkbutton_height + self.icon_width = 20 + + def do_set_property(self, pspec, value): + setattr(self, pspec.name, value) -class ShowWarningDialog(gtk.Dialog): - """ - Displays a warning to the user that downloading directly from a - camera does not always work well - """ - def __init__(self, parent_window, postChoiceCB): - gtk.Dialog.__init__(self, _("Downloading From Cameras"), None, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_OK, gtk.RESPONSE_OK)) - - self.postChoiceCB = postChoiceCB + def do_get_property(self, pspec): + return getattr(self, pspec.name) - primary_msg = _("Downloading directly from a camera may work poorly or not at all") - secondary_msg = _("Downloading from a card reader always works and is generally much faster. It is strongly recommended to use a card reader.") + def do_render(self, window, widget, background_area, cell_area, expose_area, flags): - self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) - - primary_label = gtk.Label() - primary_label.set_markup("<b>%s</b>" % primary_msg) - primary_label.set_line_wrap(True) - primary_label.set_alignment(0, 0.5) - - secondary_label = gtk.Label() - secondary_label.set_text(secondary_msg) - secondary_label.set_line_wrap(True) - secondary_label.set_alignment(0, 0.5) - - self.show_again_checkbutton = gtk.CheckButton(_('_Show this message again'), True) - self.show_again_checkbutton.set_active(True) + cairo_context = window.cairo_create() - msg_vbox = gtk.VBox() - msg_vbox.pack_start(primary_label, False, False, padding=6) - msg_vbox.pack_start(secondary_label, False, False, padding=6) - msg_vbox.pack_start(self.show_again_checkbutton) - - icon = parent_window.render_icon(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) - image = gtk.Image() - image.set_from_pixbuf(icon) - image.set_alignment(0, 0) - - warning_hbox = gtk.HBox() - warning_hbox.pack_start(image, False, False, padding = 12) - warning_hbox.pack_start(msg_vbox, False, False, padding = 12) - - self.vbox.pack_start(warning_hbox, padding=6) - - self.set_border_width(6) - self.set_has_separator(False) + x = cell_area.x + y = cell_area.y + self.checkbutton_height - 8 + w = cell_area.width + h = cell_area.height - self.set_default_response(gtk.RESPONSE_OK) - - self.set_transient_for(parent_window) - self.show_all() + #constrain operations to cell area, allowing for a 1 pixel border + #either side + #~ cairo_context.rectangle(x-1, y-1, w+2, h+2) + #~ cairo_context.clip() + + #fill in the background with dark grey + #this ensures that a selected cell's fill does not make + #the text impossible to read + #~ cairo_context.rectangle(x, y, w, h) + #~ cairo_context.set_source_rgb(0.267, 0.267, 0.267) + #~ cairo_context.fill() - self.connect('response', self.on_response) + #image width and height + image_w = self.image.size[0] + image_h = self.image.size[1] - def on_response(self, device_dialog, response): - show_again = self.show_again_checkbutton.get_active() - self.postChoiceCB(self, show_again) + #center the image horizontally + #bottom align vertically + #top left and right corners for the image: + image_x = x + ((w - image_w) / 2) + image_y = y + self.image_area_size - image_h -class UseDeviceDialog(gtk.Dialog): - def __init__(self, parent_window, path, volume, autostart, postChoiceCB): - gtk.Dialog.__init__(self, _('Device Detected'), None, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, - gtk.STOCK_YES, gtk.RESPONSE_OK)) - - self.postChoiceCB = postChoiceCB - - self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt - prompt_label = gtk.Label(_('Should this device or partition be used to download photos or videos from?')) - prompt_label.set_line_wrap(True) - prompt_hbox = gtk.HBox() - prompt_hbox.pack_start(prompt_label, False, False, padding=6) - device_label = gtk.Label() - device_label.set_markup("<b>%s</b>" % volume.get_name(limit=0)) - device_hbox = gtk.HBox() - device_hbox.pack_start(device_label, False, False) - path_label = gtk.Label() - path_label.set_markup("<i>%s</i>" % path) - path_hbox = gtk.HBox() - path_hbox.pack_start(path_label, False, False) - - icon = volume.get_icon_pixbuf(36) - if icon: - image = gtk.Image() - image.set_from_pixbuf(icon) - - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt - self.always_checkbutton = gtk.CheckButton(_('_Remember this choice'), True) - - if icon: - device_hbox_icon = gtk.HBox(homogeneous=False, spacing=6) - device_hbox_icon.pack_start(image, False, False, padding = 6) - device_vbox = gtk.VBox(homogeneous=True, spacing=6) - device_vbox.pack_start(device_hbox, False, False) - device_vbox.pack_start(path_hbox, False, False) - device_hbox_icon.pack_start(device_vbox, False, False) - self.vbox.pack_start(device_hbox_icon, padding = 6) - else: - self.vbox.pack_start(device_hbox, padding=6) - self.vbox.pack_start(path_hbox, padding = 6) - - self.vbox.pack_start(prompt_hbox, padding=6) - self.vbox.pack_start(self.always_checkbutton, padding=6) + #convert PIL image to format suitable for cairo + image = create_cairo_image_surface(self.image, image_w, image_h) - self.set_border_width(6) - self.set_has_separator(False) + # draw a light grey border of 1px around the image + cairo_context.set_source_rgb(0.66, 0.66, 0.66) #light grey, #a9a9a9 + cairo_context.set_line_width(1) + cairo_context.rectangle(image_x-.5, image_y-.5, image_w+1, image_h+1) + cairo_context.stroke() - self.set_default_response(gtk.RESPONSE_OK) - - - self.set_transient_for(parent_window) - self.show_all() - self.path = path - self.volume = volume - self.autostart = autostart - - self.connect('response', self.on_response) - - def on_response(self, device_dialog, response): - userSelected = False - permanent_choice = self.always_checkbutton.get_active() - if response == gtk.RESPONSE_OK: - userSelected = True - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt - cmd_line(_("%s selected for downloading from" % self.volume.get_name(limit=0))) - if permanent_choice: - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt - cmd_line(_("This device or partition will always be used to download from")) - else: - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt - cmd_line(_("%s rejected as a download device" % self.volume.get_name(limit=0))) - if permanent_choice: - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#usedeviceprompt - cmd_line(_("This device or partition will never be used to download from")) - - self.postChoiceCB(self, userSelected, permanent_choice, self.path, - self.volume, self.autostart) - -class RemoveAllJobCodeDialog(gtk.Dialog): - def __init__(self, parent_window, postChoiceCB): - gtk.Dialog.__init__(self, _('Remove all Job Codes?'), None, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_NO, gtk.RESPONSE_CANCEL, - gtk.STOCK_YES, gtk.RESPONSE_OK)) - - self.postChoiceCB = postChoiceCB - self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) + # draw a thin border around each cell + #~ cairo_context.set_source_rgb(0.33,0.33,0.33) + #~ cairo_context.rectangle(x, y, w, h) + #~ cairo_context.stroke() - prompt_hbox = gtk.HBox() + #place the image + cairo_context.set_source_surface(image, image_x, image_y) + cairo_context.paint() - icontheme = gtk.icon_theme_get_default() - icon = icontheme.load_icon('gtk-dialog-question', 36, gtk.ICON_LOOKUP_USE_BUILTIN) - if icon: - image = gtk.Image() - image.set_from_pixbuf(icon) - prompt_hbox.pack_start(image, False, False, padding = 6) - - prompt_label = gtk.Label(_('Should all Job Codes be removed?')) - prompt_label.set_line_wrap(True) - prompt_hbox.pack_start(prompt_label, False, False, padding=6) - - self.vbox.pack_start(prompt_hbox, padding=6) + #text + context = pangocairo.CairoContext(cairo_context) + + text_y = y + self.image_area_size + 10 + text_w = w - self.icon_width + text_x = x + self.icon_width + #~ context.rectangle(text_x, text_y, text_w, 15) + #~ context.clip() + + layout = context.create_layout() - self.set_border_width(6) - self.set_has_separator(False) + width = text_w * pango.SCALE + layout.set_width(width) - self.set_default_response(gtk.RESPONSE_OK) - - - self.set_transient_for(parent_window) - self.show_all() + layout.set_alignment(pango.ALIGN_CENTER) + layout.set_ellipsize(pango.ELLIPSIZE_END) + + #font color and size + fg_color = pango.AttrForeground(65535, 65535, 65535, 0, -1) + font_size = pango.AttrSize(8192, 0, -1) # 8 * 1024 = 8192 + font_family = pango.AttrFamily('sans', 0, -1) + attr = pango.AttrList() + attr.insert(fg_color) + attr.insert(font_size) + attr.insert(font_family) + layout.set_attributes(attr) + + layout.set_text(self.filename) + + context.move_to(text_x, text_y) + context.show_layout(layout) + #status + cairo_context.set_source_pixbuf(self.status, x, y + self.image_area_size + 10) + cairo_context.paint() - self.connect('response', self.on_response) + def do_get_size(self, widget, cell_area): + return (0, 0, self.image_area_size, self.image_area_size + self.text_area_size - self.checkbutton_height + 4) - def on_response(self, device_dialog, response): - userSelected = response == gtk.RESPONSE_OK - self.postChoiceCB(self, userSelected) + +gobject.type_register(ThumbnailCellRenderer) + + +class ThumbnailDisplay(gtk.IconView): + def __init__(self, parent_app): + gtk.IconView.__init__(self) + self.set_spacing(0) + self.set_row_spacing(5) + self.set_margin(25) + + self.rapid_app = parent_app + self.batch_size = 10 -class JobCodeDialog(gtk.Dialog): - """ Dialog prompting for a job code""" - - def __init__(self, parent_window, job_codes, default_job_code, postJobCodeEntryCB, autoStart, downloadSelected, entryOnly): - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode - gtk.Dialog.__init__(self, _('Enter a Job Code'), None, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_OK, gtk.RESPONSE_OK)) - + self.thumbnail_manager = ThumbnailManager(self.thumbnail_results, self.batch_size) + self.preview_manager = PreviewManager(self.preview_results) - self.set_icon_from_file(paths.share_dir('glade3/rapid-photo-downloader.svg')) - self.postJobCodeEntryCB = postJobCodeEntryCB - self.autoStart = autoStart - self.downloadSelected = downloadSelected + self.treerow_index = {} + self.process_index = {} - self.combobox = gtk.combo_box_entry_new_text() - for text in job_codes: - self.combobox.append_text(text) - - self.job_code_hbox = gtk.HBox(homogeneous = False) + self.rpd_files = {} - if len(job_codes) and not entryOnly: - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode - task_label = gtk.Label(_('Enter a new Job Code, or select a previous one')) - else: - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode - task_label = gtk.Label(_('Enter a new Job Code')) - task_label.set_line_wrap(True) - task_hbox = gtk.HBox() - task_hbox.pack_start(task_label, False, False, padding=6) - - label = gtk.Label(_('Job Code:')) - self.job_code_hbox.pack_start(label, False, False, padding=6) - self.job_code_hbox.pack_start(self.combobox, True, True, padding=6) + self.total_thumbs_to_generate = 0 + self.thumbnails_generated = 0 - self.set_border_width(6) - self.set_has_separator(False) - - # make entry box have entry completion - self.entry = self.combobox.child + # dict of scan_pids that are having thumbnails generated + # value is the thumbnail process id + # this is needed when terminating thumbnailing early such as when + # user clicks download before the thumbnailing is finished + self.generating_thumbnails = {} - completion = gtk.EntryCompletion() - completion.set_match_func(self.match_func) - completion.connect("match-selected", - self.on_completion_match) - completion.set_model(self.combobox.get_model()) - completion.set_text_column(0) - self.entry.set_completion(completion) + self.thumbnails = {} + self.previews = {} + self.previews_being_fetched = set() - # when user hits enter, close the dialog window - self.set_default_response(gtk.RESPONSE_OK) - self.entry.set_activates_default(True) - - if default_job_code: - self.entry.set_text(default_job_code) + self.stock_photo_thumbnails = tn.PhotoIcons() + self.stock_video_thumbnails = tn.VideoIcons() - self.vbox.pack_start(task_hbox, False, False, padding = 6) - self.vbox.pack_start(self.job_code_hbox, False, False, padding=12) + self.SELECTED_COL = 1 + self.UNIQUE_ID_COL = 2 + self.TIMESTAMP_COL = 4 + self.FILETYPE_COL = 5 + self.CHECKBUTTON_VISIBLE_COL = 6 + self.DOWNLOAD_STATUS_COL = 7 + self.STATUS_ICON_COL = 8 - self.set_transient_for(parent_window) - self.show_all() - self.connect('response', self.on_job_code_resp) - - def match_func(self, completion, key, iter): - model = completion.get_model() - return model[iter][0].lower().startswith(self.entry.get_text().lower()) - - def on_completion_match(self, completion, model, iter): - self.entry.set_text(model[iter][0]) - self.entry.set_position(-1) + self.liststore = gtk.ListStore( + gobject.TYPE_PYOBJECT, # 0 PIL thumbnail + gobject.TYPE_BOOLEAN, # 1 selected or not + str, # 2 unique id + str, # 3 file name + int, # 4 timestamp for sorting, converted float + int, # 5 file type i.e. photo or video + gobject.TYPE_BOOLEAN, # 6 visibility of checkbutton + int, # 7 status of download + gtk.gdk.Pixbuf, # 8 status icon + ) - def get_job_code(self): - return self.combobox.child.get_text() + self.clear() + self.set_model(self.liststore) - def on_job_code_resp(self, jc_dialog, response): - userChoseCode = False - if response == gtk.RESPONSE_OK: - userChoseCode = True - cmd_line(_("Job Code entered")) - else: - cmd_line(_("Job Code not entered")) - self.postJobCodeEntryCB(self, userChoseCode, self.get_job_code(), self.autoStart, self.downloadSelected) - - - -class SelectionTreeView(gtk.TreeView): - """ - TreeView display of photos and videos available for download - - Assumes a threaded environment. - """ - def __init__(self, parentApp): + + checkbutton = gtk.CellRendererToggle() + checkbutton.set_radio(False) + checkbutton.props.activatable = True + checkbutton.props.xalign = 0.0 + checkbutton.connect('toggled', self.on_checkbutton_toggled) + self.pack_end(checkbutton, expand=False) - self.parentApp = parentApp - self.rapidApp = parentApp.parentApp + self.add_attribute(checkbutton, "active", 1) + self.add_attribute(checkbutton, "visible", 6) - self.liststore = gtk.ListStore( - gtk.gdk.Pixbuf, # 0 thumbnail icon - str, # 1 name (for sorting) - int, # 2 timestamp (for sorting), float converted into an int - str, # 3 date (human readable) - int, # 4 size (for sorting) - str, # 5 size (human readable) - int, # 6 isImage (for sorting) - gtk.gdk.Pixbuf, # 7 type (photo or video) - str, # 8 job code - gobject.TYPE_PYOBJECT, # 9 mediaFile (for data) - gtk.gdk.Pixbuf, # 10 status icon - int, # 11 status (downloaded, cannot download, etc, for sorting) - str, # 12 path (on the device) - str, # 13 device - int) # 14 thread id (worker the file is associated with) - - self.selected_rows = set() - - # sort by date (unless there is a problem) - self.liststore.set_sort_column_id(2, gtk.SORT_ASCENDING) + checkbutton_size = checkbutton.get_size(self, None) + checkbutton_height = checkbutton_size[3] + checkbutton_width = checkbutton_size[2] - gtk.TreeView.__init__(self, self.liststore) + image = ThumbnailCellRenderer(checkbutton_height) + self.pack_start(image, expand=True) + self.add_attribute(image, "image", 0) + self.add_attribute(image, "filename", 3) + self.add_attribute(image, "status", 8) - selection = self.get_selection() - selection.set_mode(gtk.SELECTION_MULTIPLE) - selection.connect('changed', self.on_selection_changed) - - self.set_rubber_banding(True) - - # Status Column - # Indicates whether file was downloaded, or a warning or error of some kind - cell = gtk.CellRendererPixbuf() - cell.set_property("yalign", 0.5) - status_column = gtk.TreeViewColumn(_("Status"), cell, pixbuf=10) - status_column.set_sort_column_id(11) - status_column.connect('clicked', self.header_clicked) - self.append_column(status_column) - - # Type of file column i.e. photo or video (displays at user request) - cell = gtk.CellRendererPixbuf() - cell.set_property("yalign", 0.5) - self.type_column = gtk.TreeViewColumn(_("Type"), cell, pixbuf=7) - self.type_column.set_sort_column_id(6) - self.type_column.set_clickable(True) - self.type_column.connect('clicked', self.header_clicked) - self.append_column(self.type_column) - self.display_type_column(self.rapidApp.prefs.display_type_column) - - #File thumbnail column - if not DOWNLOAD_VIDEO: - title = _("Photo") - else: - title = _("File") - thumbnail_column = gtk.TreeViewColumn(title) - cellpb = gtk.CellRendererPixbuf() - if not DROP_SHADOW: - cellpb.set_fixed_size(60,50) - thumbnail_column.pack_start(cellpb, False) - thumbnail_column.set_attributes(cellpb, pixbuf=0) - thumbnail_column.set_sort_column_id(1) - thumbnail_column.set_clickable(True) - thumbnail_column.connect('clicked', self.header_clicked) - self.append_column(thumbnail_column) - - # Job code column - cell = gtk.CellRendererText() - cell.set_property("yalign", 0) - self.job_code_column = gtk.TreeViewColumn(_("Job Code"), cell, text=8) - self.job_code_column.set_sort_column_id(8) - self.job_code_column.set_resizable(True) - self.job_code_column.set_clickable(True) - self.job_code_column.connect('clicked', self.header_clicked) - self.append_column(self.job_code_column) - - # Date column - cell = gtk.CellRendererText() - cell.set_property("yalign", 0) - date_column = gtk.TreeViewColumn(_("Date"), cell, text=3) - date_column.set_sort_column_id(2) - date_column.set_resizable(True) - date_column.set_clickable(True) - date_column.connect('clicked', self.header_clicked) - self.append_column(date_column) - - # Size column (displays at user request) - cell = gtk.CellRendererText() - cell.set_property("yalign", 0) - self.size_column = gtk.TreeViewColumn(_("Size"), cell, text=5) - self.size_column.set_sort_column_id(4) - self.size_column.set_resizable(True) - self.size_column.set_clickable(True) - self.size_column.connect('clicked', self.header_clicked) - self.append_column(self.size_column) - self.display_size_column(self.rapidApp.prefs.display_size_column) - - # Device column (displays at user request) - cell = gtk.CellRendererText() - cell.set_property("yalign", 0) - self.device_column = gtk.TreeViewColumn(_("Device"), cell, text=13) - self.device_column.set_sort_column_id(13) - self.device_column.set_resizable(True) - self.device_column.set_clickable(True) - self.device_column.connect('clicked', self.header_clicked) - self.append_column(self.device_column) - self.display_device_column(self.rapidApp.prefs.display_device_column) - - # Filename column (displays at user request) - cell = gtk.CellRendererText() - cell.set_property("yalign", 0) - self.filename_column = gtk.TreeViewColumn(_("Filename"), cell, text=1) - self.filename_column.set_sort_column_id(1) - self.filename_column.set_resizable(True) - self.filename_column.set_clickable(True) - self.filename_column.connect('clicked', self.header_clicked) - self.append_column(self.filename_column) - self.display_filename_column(self.rapidApp.prefs.display_filename_column) - - # Path column (displays at user request) - cell = gtk.CellRendererText() - cell.set_property("yalign", 0) - self.path_column = gtk.TreeViewColumn(_("Path"), cell, text=12) - self.path_column.set_sort_column_id(12) - self.path_column.set_resizable(True) - self.path_column.set_clickable(True) - self.path_column.connect('clicked', self.header_clicked) - self.append_column(self.path_column) - self.display_path_column(self.rapidApp.prefs.display_path_column) - - self.show_all() + #set the background color to a darkish grey + self.modify_base(gtk.STATE_NORMAL, gtk.gdk.Color('#444444')) - # flag used to determine if a preview should be generated or not - # there is no point generating a preview for each photo when - # select all photos is called, for instance - self.suspend_previews = False + self.show_all() + self._setup_icons() - self.user_has_clicked_header = False + self.connect('item-activated', self.on_item_activated) + def _setup_icons(self): # icons to be displayed in status column - self.downloaded_icon = self.render_icon('rapid-photo-downloader-downloaded', gtk.ICON_SIZE_MENU) - self.download_failed_icon = self.render_icon(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) - self.error_icon = self.render_icon(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) - self.warning_icon = self.render_icon(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_MENU) - - self.download_pending_icon = self.render_icon('rapid-photo-downloader-download-pending', gtk.ICON_SIZE_MENU) - self.downloaded_with_warning_icon = self.render_icon('rapid-photo-downloader-downloaded-with-warning', gtk.ICON_SIZE_MENU) - self.downloaded_with_error_icon = self.render_icon('rapid-photo-downloader-downloaded-with-error', gtk.ICON_SIZE_MENU) + size = 16 + # standard icons + failed = self.render_icon(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) + self.download_failed_icon = failed.scale_simple(size, size, gtk.gdk.INTERP_HYPER) + error = self.render_icon(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_MENU) + self.error_icon = error.scale_simple(size, size, gtk.gdk.INTERP_HYPER) + warning = self.render_icon(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_MENU) + self.warning_icon = warning.scale_simple(size, size, gtk.gdk.INTERP_HYPER) + + # Rapid Photo Downloader specific icons + self.downloaded_icon = gtk.gdk.pixbuf_new_from_file_at_size( + paths.share_dir('glade3/rapid-photo-downloader-downloaded.svg'), + size, size) + self.download_pending_icon = gtk.gdk.pixbuf_new_from_file_at_size( + paths.share_dir('glade3/rapid-photo-downloader-download-pending.png'), + size, size) + self.downloaded_with_warning_icon = gtk.gdk.pixbuf_new_from_file_at_size( + paths.share_dir('glade3/rapid-photo-downloader-downloaded-with-warning.svg'), + size, size) + self.downloaded_with_error_icon = gtk.gdk.pixbuf_new_from_file_at_size( + paths.share_dir('glade3/rapid-photo-downloader-downloaded-with-error.svg'), + size, size) # make the not yet downloaded icon a transparent square self.not_downloaded_icon = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, 16, 16) self.not_downloaded_icon.fill(0xffffffff) self.not_downloaded_icon = self.not_downloaded_icon.add_alpha(True, chr(255), chr(255), chr(255)) - # but make it be a tick in the preview pane - self.not_downloaded_icon_tick = self.render_icon(gtk.STOCK_YES, gtk.ICON_SIZE_MENU) - - #preload generic icons - self.icon_photo = gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/photo24.png')) - self.icon_video = gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/video24.png')) - #with shadows - if DROP_SHADOW: - self.generic_photo_thumbnail = gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/photo_small_shadow.png')) - self.generic_video_thumbnail = gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/video_small_shadow.png')) - self.iconDropShadow = DropShadow(offset=(3,3), shadow = (0x34, 0x34, 0x34, 0xff), border=6) - else: - self.generic_photo_thumbnail = gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/photo_small.png')) - self.generic_video_thumbnail = gtk.gdk.pixbuf_new_from_file(paths.share_dir('glade3/video_small.png')) - - self.previewed_file_treerowref = None - self.icontheme = gtk.icon_theme_get_default() - - - def get_thread(self, iter): - """ - Returns the thread associated with the liststore's iter - """ - return self.liststore.get_value(iter, 14) - - def get_status(self, iter): - """ - Returns the status associated with the liststore's iter - """ - return self.liststore.get_value(iter, 11) - - def get_mediaFile(self, iter): - """ - Returns the mediaFile associated with the liststore's iter - """ - return self.liststore.get_value(iter, 9) - - def get_is_image(self, iter): - """ - Returns the file type (is image or video) associated with the liststore's iter - """ - return self.liststore.get_value(iter, 6) - - def get_type_icon(self, iter): - """ - Returns the file type's pixbuf associated with the liststore's iter - """ - return self.liststore.get_value(iter, 7) - - def get_job_code(self, iter): - """ - Returns the job code associated with the liststore's iter - """ - return self.liststore.get_value(iter, 8) - - def get_status_icon(self, status, preview=False): + def get_status_icon(self, status): """ Returns the correct icon, based on the status """ @@ -3679,10 +577,7 @@ class SelectionTreeView(gtk.TreeView): elif status == STATUS_DOWNLOADED: status_icon = self.downloaded_icon elif status == STATUS_NOT_DOWNLOADED: - if preview: - status_icon = self.not_downloaded_icon_tick - else: - status_icon = self.not_downloaded_icon + status_icon = self.not_downloaded_icon elif status in [STATUS_DOWNLOADED_WITH_WARNING, STATUS_BACKUP_PROBLEM]: status_icon = self.downloaded_with_warning_icon elif status in [STATUS_DOWNLOAD_FAILED, STATUS_DOWNLOAD_AND_BACKUP_FAILED]: @@ -3690,1469 +585,1412 @@ class SelectionTreeView(gtk.TreeView): elif status == STATUS_DOWNLOAD_PENDING: status_icon = self.download_pending_icon else: - sys.stderr.write("FIXME: unknown status: %s\n" % status) + logger.critical("FIXME: unknown status: %s", status) status_icon = self.not_downloaded_icon - return status_icon - - def get_tree_row_refs(self): - """ - Returns a list of all tree row references - """ - tree_row_refs = [] - iter = self.liststore.get_iter_first() - while iter: - tree_row_refs.append(self.get_mediaFile(iter).treerowref) - iter = self.liststore.iter_next(iter) - return tree_row_refs - - def get_selected_tree_row_refs(self): - """ - Returns a list of tree row references for the selected rows - """ - tree_row_refs = [] - selection = self.get_selection() - model, pathlist = selection.get_selected_rows() - for path in pathlist: - iter = self.liststore.get_iter(path) - tree_row_refs.append(self.get_mediaFile(iter).treerowref) - return tree_row_refs - - def get_tree_row_iters(self, selected_only=False): - """ - Yields tree row iters + return status_icon + + def sort_by_timestamp(self): + self.liststore.set_sort_column_id(self.TIMESTAMP_COL, gtk.SORT_ASCENDING) - If selected_only is True, then only those from the selected - rows will be returned. + def on_checkbutton_toggled(self, cellrenderertoggle, path): + iter = self.liststore.get_iter(path) + self.liststore.set_value(iter, self.SELECTED_COL, not cellrenderertoggle.get_active()) + self.rapid_app.set_download_action_sensitivity() - This function is essential when modifying any content - in the list store (because rows can easily be moved when their - content changes) - """ - if selected_only: - tree_row_refs = self.get_selected_tree_row_refs() - else: - tree_row_refs = self.get_tree_row_refs() - for reference in tree_row_refs: - path = reference.get_path() - yield self.liststore.get_iter(path) + def set_selected(self, unique_id, value): + iter = self.get_iter_from_unique_id(unique_id) + self.liststore.set_value(iter, self.SELECTED_COL, value) - def add_file(self, mediaFile): - if debug_info: - cmd_line('Adding file %s' % mediaFile.fullFileName) - - # metadata is loaded when previews are generated before downloading - if mediaFile.metadata: - date = mediaFile.dateTime() - timestamp = mediaFile.metadata.timeStamp(missing=None) - if timestamp is None: - timestamp = mediaFile.modificationTime - # if metadata has not been loaded, substitute other values - else: - timestamp = mediaFile.modificationTime - date = datetime.datetime.fromtimestamp(timestamp) + def add_file(self, rpd_file, generate_thumbnail): - timestamp = int(timestamp) - - date_human_readable = date_time_human_readable(date) - name = mediaFile.name - size = mediaFile.size - thumbnail = mediaFile.thumbnail - - if mediaFile.genericThumbnail: - if mediaFile.isImage: - thumbnail_icon = self.generic_photo_thumbnail - else: - thumbnail_icon = self.generic_video_thumbnail - else: - thumbnail_icon = common.scale2pixbuf(60, 36, thumbnail) - - if DROP_SHADOW and not mediaFile.genericThumbnail: - pil_image = pixbuf_to_image(thumbnail_icon) - pil_image = self.iconDropShadow.dropShadow(pil_image) - thumbnail_icon = image_to_pixbuf(pil_image) + thumbnail_icon = self.get_stock_icon(rpd_file.file_type) + unique_id = rpd_file.unique_id + scan_pid = rpd_file.scan_pid + timestamp = int(rpd_file.modification_time) + + iter = self.liststore.append((thumbnail_icon, + True, + unique_id, + rpd_file.display_name, + timestamp, + rpd_file.file_type, + True, + STATUS_NOT_DOWNLOADED, + self.not_downloaded_icon + )) - if mediaFile.isImage: - type_icon = self.icon_photo - else: - type_icon = self.icon_video - - status_icon = self.get_status_icon(mediaFile.status) - - if debug_info and False: - cmd_line('Thumbnail icon: %s' % thumbnail_icon) - cmd_line('Name: %s' % name) - cmd_line('Timestamp: %s' % timestamp) - cmd_line('Date: %s' % date_human_readable) - cmd_line('Size: %s %s' % (size, common.formatSizeForUser(size))) - cmd_line('Is an image: %s' % mediaFile.isImage) - cmd_line('Status: %s' % self.status_human_readable(mediaFile)) - cmd_line('Path: %s' % mediaFile.path) - cmd_line('Device name: %s' % mediaFile.deviceName) - cmd_line('Thread: %s' % mediaFile.thread_id) - cmd_line(' ') - - iter = self.liststore.append((thumbnail_icon, name, timestamp, date_human_readable, size, common.formatSizeForUser(size), mediaFile.isImage, type_icon, '', mediaFile, status_icon, mediaFile.status, mediaFile.path, mediaFile.deviceName, mediaFile.thread_id)) - - #create a reference to this row and store it in the mediaFile path = self.liststore.get_path(iter) - mediaFile.treerowref = gtk.TreeRowReference(self.liststore, path) + treerowref = gtk.TreeRowReference(self.liststore, path) - if mediaFile.status in [STATUS_CANNOT_DOWNLOAD, STATUS_WARNING]: - if not self.user_has_clicked_header: - self.liststore.set_sort_column_id(11, gtk.SORT_DESCENDING) + if scan_pid in self.process_index: + self.process_index[scan_pid].append(unique_id) + else: + self.process_index[scan_pid] = [unique_id,] + + self.treerow_index[unique_id] = treerowref + self.rpd_files[unique_id] = rpd_file - def no_selected_rows_available_for_download(self): - """ - Gets the number of rows the user has selected that can actually - be downloaded, and the threads they are found in - """ - v = 0 - threads = [] - model, paths = self.get_selection().get_selected_rows() - for path in paths: - iter = self.liststore.get_iter(path) - status = self.get_status(iter) - if status in [STATUS_NOT_DOWNLOADED, STATUS_WARNING]: - v += 1 - thread = self.get_thread(iter) - if thread not in threads: - threads.append(thread) - return v, threads - - def rows_available_for_download(self): - """ - Returns true if one or more rows has their status as STATUS_NOT_DOWNLOADED or STATUS_WARNING - """ - iter = self.liststore.get_iter_first() - while iter: - status = self.get_status(iter) - if status in [STATUS_NOT_DOWNLOADED, STATUS_WARNING]: - return True - iter = self.liststore.iter_next(iter) - return False + if generate_thumbnail: + self.total_thumbs_to_generate += 1 + + def get_sample_file(self, file_type): + """Returns an rpd_file for of a given file type, or None if it does + not exist""" + for unique_id, rpd_file in self.rpd_files.iteritems(): + if rpd_file.file_type == file_type: + if rpd_file.status <> STATUS_CANNOT_DOWNLOAD: + return rpd_file + + return None + + def get_unique_id_from_iter(self, iter): + return self.liststore.get_value(iter, 2) + + def get_iter_from_unique_id(self, unique_id): + treerowref = self.treerow_index[unique_id] + path = treerowref.get_path() + return self.liststore.get_iter(path) - def update_download_selected_button(self): + def on_item_activated(self, iconview, path): """ - Updates the text on the Download Selection button, and set its sensitivity """ - no_available_for_download = 0 - selection = self.get_selection() - model, paths = selection.get_selected_rows() - if paths: - path = paths[0] + iter = self.liststore.get_iter(path) + self.show_preview(iter=iter) + self.advance_get_preview_image(iter) + + + def _get_preview(self, unique_id, rpd_file): + if unique_id not in self.previews_being_fetched: + #check if preview should be from a downloaded file, or the source + if rpd_file.status in DOWNLOADED: + file_location = rpd_file.download_full_file_name + else: + file_location = rpd_file.full_file_name + self.preview_manager.get_preview(unique_id, file_location, + rpd_file.file_type, size_max=None,) + + self.previews_being_fetched.add(unique_id) + + def show_preview(self, unique_id=None, iter=None): + if unique_id is not None: + iter = self.get_iter_from_unique_id(unique_id) + elif iter is not None: + unique_id = self.get_unique_id_from_iter(iter) + else: + # neither an iter or a unique_id were passed + # use iter from first selected file + # if none is selected, choose the first file + selected = self.get_selected_items() + if selected: + path = selected[0] + else: + path = 0 iter = self.liststore.get_iter(path) + unique_id = self.get_unique_id_from_iter(iter) - #update button text - no_available_for_download, threads = self.no_selected_rows_available_for_download() - if no_available_for_download and workers.scanComplete(threads): - self.rapidApp.download_selected_button.set_label(self.rapidApp.DOWNLOAD_SELECTED_LABEL + " (%s)" % no_available_for_download) - self.rapidApp.download_selected_button.set_sensitive(True) - else: - #nothing was selected, or nothing is available from what the user selected, or should not download right now - self.rapidApp.download_selected_button.set_label(self.rapidApp.DOWNLOAD_SELECTED_LABEL) - self.rapidApp.download_selected_button.set_sensitive(False) - - def on_selection_changed(self, selection): - """ - Update download selected button and preview the most recently - selected row in the treeview - """ - self.update_download_selected_button() - size = selection.count_selected_rows() - if size == 0: - self.selected_rows = set() - self.show_preview(None) + rpd_file = self.rpd_files[unique_id] + + if unique_id in self.previews: + preview_image = self.previews[unique_id] else: - if size <= len(self.selected_rows): - # discard everything, start over - self.selected_rows = set() - self.selection_size = size - model, paths = selection.get_selected_rows() - for path in paths: - iter = self.liststore.get_iter(path) - ref = self.get_mediaFile(iter).treerowref - - if ref not in self.selected_rows: - self.show_preview(iter) - self.selected_rows.add(ref) + # request daemon process to get a full size thumbnail + self._get_preview(unique_id, rpd_file) + if unique_id in self.thumbnails: + preview_image = self.thumbnails[unique_id] + else: + preview_image = self.get_stock_icon(rpd_file.file_type) + + checked = self.liststore.get_value(iter, self.SELECTED_COL) + include_checkbutton_visible = rpd_file.status == STATUS_NOT_DOWNLOADED + self.rapid_app.show_preview_image(unique_id, preview_image, + include_checkbutton_visible, checked) - def clear_all(self, thread_id = None): - if thread_id is None: - self.liststore.clear() - self.show_preview(None) - else: + def _get_next_iter(self, iter): + iter = self.liststore.iter_next(iter) + if iter is None: iter = self.liststore.get_iter_first() - while iter: - t = self.get_thread(iter) - if t == thread_id: - if self.previewed_file_treerowref: - mediaFile = self.get_mediaFile(iter) - if mediaFile.treerowref == self.previewed_file_treerowref: - self.show_preview(None) - self.liststore.remove(iter) - # need to start over, or else bad things happen - iter = self.liststore.get_iter_first() - else: - iter = self.liststore.iter_next(iter) + return iter + + def _get_prev_iter(self, iter): + row = self.liststore.get_path(iter)[0] + if row == 0: + row = len(self.liststore)-1 + else: + row -= 1 + iter = self.liststore.get_iter(row) + return iter - def refreshSampleDownloadFolders(self, thread_id = None): + def show_next_image(self, unique_id): + iter = self.get_iter_from_unique_id(unique_id) + iter = self._get_next_iter(iter) + + if iter is not None: + self.show_preview(iter=iter) + + # cache next image + self.advance_get_preview_image(iter, prev=False, next=True) + + def show_prev_image(self, unique_id): + iter = self.get_iter_from_unique_id(unique_id) + iter = self._get_prev_iter(iter) + + if iter is not None: + self.show_preview(iter=iter) + + # cache next image + self.advance_get_preview_image(iter, prev=True, next=False) + + + def advance_get_preview_image(self, iter, prev=True, next=True): + unique_ids = [] + if next: + next_iter = self._get_next_iter(iter) + unique_ids.append(self.get_unique_id_from_iter(next_iter)) + + if prev: + prev_iter = self._get_prev_iter(iter) + unique_ids.append(self.get_unique_id_from_iter(prev_iter)) + + for unique_id in unique_ids: + if not unique_id in self.previews: + rpd_file = self.rpd_files[unique_id] + self._get_preview(unique_id, rpd_file) + + def check_all(self, check_all, file_type=None): + for row in self.liststore: + if row[self.CHECKBUTTON_VISIBLE_COL]: + if file_type is not None: + if row[self.FILETYPE_COL] == file_type: + row[self.SELECTED_COL] = check_all + else: + row[self.SELECTED_COL] = check_all + self.rapid_app.set_download_action_sensitivity() + + def files_are_checked_to_download(self): """ - Refreshes the download folder of every file that has not yet been downloaded + Returns True if there is any file that the user has indicated they + intend to download, else returns False. + """ + for row in self.liststore: + if row[self.SELECTED_COL]: + rpd_file = self.rpd_files[row[self.UNIQUE_ID_COL]] + if rpd_file.status not in DOWNLOADED: + return True + return False - This is useful when the user updates the preferences, and the scan has already occurred (or is occurring) + def get_files_checked_for_download(self, scan_pid): + """ + Returns a dict of scan ids and associated files the user has indicated + they want to download - If thread_id is specified, will only update rows with that thread + If scan_pid is not None, then returns only those files from that scan_pid """ - for iter in self.get_tree_row_iters(): - status = self.get_status(iter) - if status in [STATUS_NOT_DOWNLOADED, STATUS_WARNING, STATUS_CANNOT_DOWNLOAD]: - regenerate = True - if thread_id is not None: - t = self.get_thread(iter) - regenerate = t == thread_id + files = dict() + if scan_pid is None: + for row in self.liststore: + if row[self.SELECTED_COL]: + rpd_file = self.rpd_files[row[self.UNIQUE_ID_COL]] + if rpd_file.status not in DOWNLOADED: + scan_pid = rpd_file.scan_pid + if scan_pid in files: + files[scan_pid].append(rpd_file) + else: + files[scan_pid] = [rpd_file,] + else: + files[scan_pid] = [] + for unique_id in self.process_index[scan_pid]: + rpd_file = self.rpd_files[unique_id] + if rpd_file.status not in DOWNLOADED: + iter = self.get_iter_from_unique_id(unique_id) + if self.liststore.get_value(iter, self.SELECTED_COL): + files[scan_pid].append(rpd_file) + return files - if regenerate: - mediaFile = self.get_mediaFile(iter) - if mediaFile.isImage: - mediaFile.downloadFolder = self.rapidApp.prefs.download_folder - else: - mediaFile.downloadFolder = self.rapidApp.prefs.video_download_folder - mediaFile.samplePath = os.path.join(mediaFile.downloadFolder, mediaFile.sampleSubfolder) - if mediaFile.treerowref == self.previewed_file_treerowref: - self.show_preview(iter) - - def _refreshNameFactories(self): - sample_download_start_time = datetime.datetime.now() - self.imageRenamePrefsFactory = rn.ImageRenamePreferences(self.rapidApp.prefs.image_rename, self, - self.rapidApp.fileSequenceLock, sequences) - self.imageRenamePrefsFactory.setDownloadStartTime(sample_download_start_time) - self.videoRenamePrefsFactory = rn.VideoRenamePreferences(self.rapidApp.prefs.video_rename, self, - self.rapidApp.fileSequenceLock, sequences) - self.videoRenamePrefsFactory.setDownloadStartTime(sample_download_start_time) - self.subfolderPrefsFactory = rn.SubfolderPreferences(self.rapidApp.prefs.subfolder, self) - self.subfolderPrefsFactory.setDownloadStartTime(sample_download_start_time) - self.videoSubfolderPrefsFactory = rn.VideoSubfolderPreferences(self.rapidApp.prefs.video_subfolder, self) - self.videoSubfolderPrefsFactory.setDownloadStartTime(sample_download_start_time) - self.strip_characters = self.rapidApp.prefs.strip_characters - - - def refreshGeneratedSampleSubfolderAndName(self, thread_id = None): + def get_no_files_remaining(self, scan_pid): """ - Refreshes the name, subfolder and status of every file that has not yet been downloaded - - This is useful when the user updates the preferences, and the scan has already occurred (or is occurring) + Returns the number of files that have not yet been downloaded for the + scan_pid + """ + i = 0 + for unique_id in self.process_index[scan_pid]: + rpd_file = self.rpd_files[unique_id] + if rpd_file.status == STATUS_NOT_DOWNLOADED: + i += 1 + return i - If thread_id is specified, will only update rows with that thread + def files_remain_to_download(self): + """ + Returns True if any files remain that are not downloaded, else returns + False + """ + for row in self.liststore: + if row[self.DOWNLOAD_STATUS_COL] == STATUS_NOT_DOWNLOADED: + return True + return False + + + def mark_download_pending(self, files_by_scan_pid): """ - self._setUsesJobCode() - self._refreshNameFactories() - for iter in self.get_tree_row_iters(): - status = self.get_status(iter) - if status in [STATUS_NOT_DOWNLOADED, STATUS_WARNING, STATUS_CANNOT_DOWNLOAD]: - regenerate = True - if thread_id is not None: - t = self.get_thread(iter) - regenerate = t == thread_id + Sets status to download pending and updates thumbnails display + """ + for scan_pid in files_by_scan_pid: + for rpd_file in files_by_scan_pid[scan_pid]: + unique_id = rpd_file.unique_id + self.rpd_files[unique_id].status = STATUS_DOWNLOAD_PENDING + iter = self.get_iter_from_unique_id(unique_id) + if not self.rapid_app.auto_start_is_on: + # don't make the checkbox invisible immediately when on auto start + # otherwise the box can be rendred at the wrong size, as it is + # realized after the checkbox has already been made invisible + self.liststore.set_value(iter, self.CHECKBUTTON_VISIBLE_COL, False) + self.liststore.set_value(iter, self.SELECTED_COL, False) + self.liststore.set_value(iter, self.DOWNLOAD_STATUS_COL, STATUS_DOWNLOAD_PENDING) + icon = self.get_status_icon(STATUS_DOWNLOAD_PENDING) + self.liststore.set_value(iter, self.STATUS_ICON_COL, icon) - if regenerate: - mediaFile = self.get_mediaFile(iter) - self.generateSampleSubfolderAndName(mediaFile, iter) - if mediaFile.treerowref == self.previewed_file_treerowref: - self.show_preview(iter) - - def generateSampleSubfolderAndName(self, mediaFile, iter): - problem = pn.Problem() - if mediaFile.isImage: - fallback_date = None - subfolderPrefsFactory = self.subfolderPrefsFactory - renamePrefsFactory = self.imageRenamePrefsFactory - nameUsesJobCode = self.imageRenameUsesJobCode - subfolderUsesJobCode = self.imageSubfolderUsesJobCode + def select_image(self, unique_id): + iter = self.get_iter_from_unique_id(unique_id) + path = self.liststore.get_path(iter) + self.select_path(path) + self.scroll_to_path(path, use_align=False, row_align=0.5, col_align=0.5) + + def get_stock_icon(self, file_type): + if file_type == rpdfile.FILE_TYPE_PHOTO: + return self.stock_photo_thumbnails.stock_thumbnail_image_icon else: - fallback_date = mediaFile.modificationTime - subfolderPrefsFactory = self.videoSubfolderPrefsFactory - renamePrefsFactory = self.videoRenamePrefsFactory - nameUsesJobCode = self.videoRenameUsesJobCode - subfolderUsesJobCode = self.videoSubfolderUsesJobCode + return self.stock_video_thumbnails.stock_thumbnail_image_icon - renamePrefsFactory.setJobCode(self.get_job_code(iter)) - subfolderPrefsFactory.setJobCode(self.get_job_code(iter)) - - generateSubfolderAndName(mediaFile, problem, subfolderPrefsFactory, renamePrefsFactory, - nameUsesJobCode, subfolderUsesJobCode, - self.strip_characters, fallback_date) - if self.get_status(iter) != mediaFile.status: - self.liststore.set(iter, 11, mediaFile.status) - self.liststore.set(iter, 10, self.get_status_icon(mediaFile.status)) - mediaFile.sampleStale = False - - def _setUsesJobCode(self): - self.imageRenameUsesJobCode = rn.usesJobCode(self.rapidApp.prefs.image_rename) - self.imageSubfolderUsesJobCode = rn.usesJobCode(self.rapidApp.prefs.subfolder) - self.videoRenameUsesJobCode = rn.usesJobCode(self.rapidApp.prefs.video_rename) - self.videoSubfolderUsesJobCode = rn.usesJobCode(self.rapidApp.prefs.video_subfolder) + def update_status_post_download(self, rpd_file): + iter = self.get_iter_from_unique_id(rpd_file.unique_id) + self.liststore.set_value(iter, self.DOWNLOAD_STATUS_COL, rpd_file.status) + icon = self.get_status_icon(rpd_file.status) + self.liststore.set_value(iter, self.STATUS_ICON_COL, icon) + self.liststore.set_value(iter, self.CHECKBUTTON_VISIBLE_COL, False) + self.rpd_files[rpd_file.unique_id] = rpd_file + + def generate_thumbnails(self, scan_pid): + """Initiate thumbnail generation for files scanned in one process + """ + rpd_files = [self.rpd_files[unique_id] for unique_id in self.process_index[scan_pid]] + thumbnail_pid = self.thumbnail_manager.add_task((scan_pid, rpd_files)) + self.generating_thumbnails[scan_pid] = thumbnail_pid + def _set_thumbnail(self, unique_id, icon): + treerowref = self.treerow_index[unique_id] + path = treerowref.get_path() + iter = self.liststore.get_iter(path) + self.liststore.set(iter, 0, icon) - def status_human_readable(self, mediaFile): - if mediaFile.status == STATUS_DOWNLOADED: - v = _('%(filetype)s was downloaded successfully') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_DOWNLOAD_FAILED: - v = _('%(filetype)s was not downloaded') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_DOWNLOADED_WITH_WARNING: - v = _('%(filetype)s was downloaded with warnings') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_BACKUP_PROBLEM: - v = _('%(filetype)s was downloaded but there were problems backing up') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_DOWNLOAD_AND_BACKUP_FAILED: - v = _('%(filetype)s was neither downloaded nor backed up') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_NOT_DOWNLOADED: - v = _('%(filetype)s is ready to be downloaded') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_DOWNLOAD_PENDING: - v = _('%(filetype)s is about to be downloaded') % {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_WARNING: - v = _('%(filetype)s will be downloaded with warnings')% {'filetype': mediaFile.displayNameCap} - elif mediaFile.status == STATUS_CANNOT_DOWNLOAD: - v = _('%(filetype)s cannot be downloaded') % {'filetype': mediaFile.displayNameCap} - return v - - def show_preview(self, iter): + def update_thumbnail(self, thumbnail_data): + """ + Takes the generated thumbnail and updates the display + + If the thumbnail_data includes a second image, that is used to + update the thumbnail list using the unique_id + """ + unique_id = thumbnail_data[0] + thumbnail_icon = thumbnail_data[1] + + if thumbnail_icon is not None: + # get the thumbnail icon in PIL format + thumbnail_icon = thumbnail_icon.get_image() - if not iter: - # clear everything except the label Preview at the top - for widget in [self.parentApp.preview_original_name_label, - self.parentApp.preview_name_label, - self.parentApp.preview_status_label, - self.parentApp.preview_problem_title_label, - self.parentApp.preview_problem_label]: - widget.set_text('') - - for widget in [self.parentApp.preview_image, - self.parentApp.preview_name_label, - self.parentApp.preview_original_name_label, - self.parentApp.preview_status_label, - self.parentApp.preview_problem_title_label, - self.parentApp.preview_problem_label - ]: - widget.set_tooltip_text('') + if thumbnail_icon: + self._set_thumbnail(unique_id, thumbnail_icon) - self.parentApp.preview_image.clear() - self.parentApp.preview_status_icon.clear() - self.parentApp.preview_destination_expander.hide() - self.parentApp.preview_device_expander.hide() - self.previewed_file_treerowref = None - + if len(thumbnail_data) > 2: + # get the 2nd image in PIL format + self.thumbnails[unique_id] = thumbnail_data[2].get_image() + + def terminate_thumbnail_generation(self, scan_pid): + """ + Terminates thumbnail generation if thumbnails are currently + being generated for this scan_pid + """ - elif not self.suspend_previews: - mediaFile = self.get_mediaFile(iter) + if scan_pid in self.generating_thumbnails: + terminated = True + self.thumbnail_manager.terminate_process( + self.generating_thumbnails[scan_pid]) + del self.generating_thumbnails[scan_pid] - self.previewed_file_treerowref = mediaFile.treerowref + if len(self.generating_thumbnails) == 0: + self._reset_thumbnail_tracking_and_display() + else: + terminated = False - self.parentApp.set_base_preview_image(mediaFile.thumbnail) - thumbnail = self.parentApp.scaledPreviewImage() + return terminated - self.parentApp.preview_image.set_from_pixbuf(thumbnail) + def mark_thumbnails_needed(self, rpd_files): + for rpd_file in rpd_files: + if rpd_file.unique_id not in self.thumbnails: + rpd_file.generate_thumbnail = True + + def _reset_thumbnail_tracking_and_display(self): + self.rapid_app.download_progressbar.set_fraction(0.0) + self.rapid_app.download_progressbar.set_text('') + self.thumbnails_generated = 0 + self.total_thumbs_to_generate = 0 + + def thumbnail_results(self, source, condition): + connection = self.thumbnail_manager.get_pipe(source) + + conn_type, data = connection.recv() + + if conn_type == rpdmp.CONN_COMPLETE: + scan_pid = data + del self.generating_thumbnails[scan_pid] + connection.close() + return False + else: - image_tool_tip = "%s\n%s" % (date_time_human_readable(mediaFile.dateTime(), False), common.formatSizeForUser(mediaFile.size)) - self.parentApp.preview_image.set_tooltip_text(image_tool_tip) - - if mediaFile.sampleStale and mediaFile.status in [STATUS_NOT_DOWNLOADED, STATUS_WARNING]: - self._refreshNameFactories() - self._setUsesJobCode() - self.generateSampleSubfolderAndName(mediaFile, iter) - - self.parentApp.preview_original_name_label.set_text(mediaFile.name) - self.parentApp.preview_original_name_label.set_tooltip_text(mediaFile.name) - if mediaFile.volume: - pixbuf = mediaFile.volume.get_icon_pixbuf(16) - else: - pixbuf = self.icontheme.load_icon('gtk-harddisk', 16, gtk.ICON_LOOKUP_USE_BUILTIN) - self.parentApp.preview_device_image.set_from_pixbuf(pixbuf) - self.parentApp.preview_device_label.set_text(mediaFile.deviceName) - self.parentApp.preview_device_path_label.set_text(mediaFile.path) - self.parentApp.preview_device_path_label.set_tooltip_text(mediaFile.path) + for thumbnail_data in data: + self.update_thumbnail(thumbnail_data) - if using_gio: - folder = gio.File(mediaFile.downloadFolder) - fileInfo = folder.query_info(gio.FILE_ATTRIBUTE_STANDARD_ICON) - icon = fileInfo.get_icon() - pixbuf = common.get_icon_pixbuf(using_gio, icon, 16, fallback='folder') - else: - pixbuf = self.icontheme.load_icon('folder', 16, gtk.ICON_LOOKUP_USE_BUILTIN) - - self.parentApp.preview_destination_image.set_from_pixbuf(pixbuf) - downloadFolderName = os.path.split(mediaFile.downloadFolder)[1] - self.parentApp.preview_destination_label.set_text(downloadFolderName) - - if mediaFile.status in [STATUS_WARNING, STATUS_CANNOT_DOWNLOAD, STATUS_NOT_DOWNLOADED, STATUS_DOWNLOAD_PENDING]: - - self.parentApp.preview_name_label.set_text(mediaFile.sampleName) - self.parentApp.preview_name_label.set_tooltip_text(mediaFile.sampleName) - self.parentApp.preview_destination_path_label.set_text(mediaFile.samplePath) - self.parentApp.preview_destination_path_label.set_tooltip_text(mediaFile.samplePath) - else: - self.parentApp.preview_name_label.set_text(mediaFile.downloadName) - self.parentApp.preview_name_label.set_tooltip_text(mediaFile.downloadName) - self.parentApp.preview_destination_path_label.set_text(mediaFile.downloadPath) - self.parentApp.preview_destination_path_label.set_tooltip_text(mediaFile.downloadPath) + self.thumbnails_generated += len(data) - status_text = self.status_human_readable(mediaFile) - self.parentApp.preview_status_icon.set_from_pixbuf(self.get_status_icon(mediaFile.status, preview=True)) - self.parentApp.preview_status_label.set_markup('<b>' + status_text + '</b>') - self.parentApp.preview_status_label.set_tooltip_text(status_text) - - - if mediaFile.status in [STATUS_WARNING, STATUS_DOWNLOAD_FAILED, - STATUS_DOWNLOADED_WITH_WARNING, - STATUS_CANNOT_DOWNLOAD, - STATUS_BACKUP_PROBLEM, - STATUS_DOWNLOAD_AND_BACKUP_FAILED]: - problem_title = mediaFile.problem.get_title() - self.parentApp.preview_problem_title_label.set_markup('<i>' + problem_title + '</i>') - self.parentApp.preview_problem_title_label.set_tooltip_text(problem_title) - - problem_text = mediaFile.problem.get_problems() - self.parentApp.preview_problem_label.set_text(problem_text) - self.parentApp.preview_problem_label.set_tooltip_text(problem_text) + # clear progress bar information if all thumbnails have been + # extracted + if self.thumbnails_generated == self.total_thumbs_to_generate: + self._reset_thumbnail_tracking_and_display() else: - self.parentApp.preview_problem_label.set_markup('') - self.parentApp.preview_problem_title_label.set_markup('') - for widget in [self.parentApp.preview_problem_title_label, - self.parentApp.preview_problem_label - ]: - widget.set_tooltip_text('') - - if self.rapidApp.prefs.display_preview_folders: - self.parentApp.preview_destination_expander.show() - self.parentApp.preview_device_expander.show() - - - def select_rows(self, range): - selection = self.get_selection() - if range == 'all': - selection.select_all() - elif range == 'none': - selection.unselect_all() - else: - # User chose to select all photos or all videos, - # or select all files with or without job codes. - - # Temporarily suspend previews while a large number of rows - # are being selected / unselected - self.suspend_previews = True - - iter = self.liststore.get_iter_first() - while iter is not None: - if range in ['photos', 'videos']: - type = self.get_is_image(iter) - select_row = (type and range == 'photos') or (not type and range == 'videos') - else: - job_code = self.get_job_code(iter) - select_row = (job_code and range == 'withjobcode') or (not job_code and range == 'withoutjobcode') - - if select_row: - selection.select_iter(iter) - else: - selection.unselect_iter(iter) - iter = self.liststore.iter_next(iter) + if self.total_thumbs_to_generate: + self.rapid_app.download_progressbar.set_fraction( + float(self.thumbnails_generated) / self.total_thumbs_to_generate) - self.suspend_previews = False - # select the first photo / video - iter = self.liststore.get_iter_first() - while iter is not None: - type = self.get_is_image(iter) - if (type and range == 'photos') or (not type and range == 'videos'): - self.show_preview(iter) - break - iter = self.liststore.iter_next(iter) - - - def header_clicked(self, column): - self.user_has_clicked_header = True - def display_filename_column(self, display): + return True + + def preview_results(self, unique_id, preview_full_size, preview_small): """ - if display is true, the column will be shown - otherwise, it will not be shown + Receive a full size preview image and update """ - self.filename_column.set_visible(display) + self.previews_being_fetched.remove(unique_id) + if preview_full_size: + preview_image = preview_full_size.get_image() + self.previews[unique_id] = preview_image + self.rapid_app.update_preview_image(unique_id, preview_image) + + # user can turn off option for thumbnail generation after a scan + if unique_id not in self.thumbnails: + self._set_thumbnail(unique_id, preview_small.get_image()) + + + def clear_all(self, scan_pid=None, keep_downloaded_files=False): + """ + Removes files from display and internal tracking. - def display_size_column(self, display): - self.size_column.set_visible(display) + If scan_pid is not None, then only files matching that scan_pid will + be removed. Otherwise, everything will be removed. + + If keep_downloaded_files is True, files will not be removed if they + have been downloaded. + """ + if scan_pid is None and not keep_downloaded_files: + self.liststore.clear() + self.treerow_index = {} + self.process_index = {} + + self.rpd_files = {} + else: + if scan_pid in self.process_index: + for unique_id in self.process_index[scan_pid]: + rpd_file = self.rpd_files[unique_id] + if not keep_downloaded_files or not rpd_file.status in DOWNLOADED: + treerowref = self.treerow_index[rpd_file.unique_id] + path = treerowref.get_path() + iter = self.liststore.get_iter(path) + self.liststore.remove(iter) + del self.treerow_index[rpd_file.unique_id] + del self.rpd_files[rpd_file.unique_id] + if not keep_downloaded_files or not len(self.process_index[scan_pid]): + del self.process_index[scan_pid] + +class TaskManager: + def __init__(self, results_callback, batch_size): + self.results_callback = results_callback + + # List of actual process, it's terminate_queue, and it's run_event + self._processes = [] + + self._pipes = {} + self.batch_size = batch_size + + self.paused = False + self.no_tasks = 0 + + + def add_task(self, task): + pid = self._setup_task(task) + logger.debug("TaskManager PID: %s", pid) + self.no_tasks += 1 + return pid - def display_type_column(self, display): - if not DOWNLOAD_VIDEO: - self.type_column.set_visible(False) - else: - self.type_column.set_visible(display) - def display_path_column(self, display): - self.path_column.set_visible(display) + def _setup_task(self, task): + task_results_conn, task_process_conn = self._setup_pipe() - def display_device_column(self, display): - self.device_column.set_visible(display) + source = task_results_conn.fileno() + self._pipes[source] = task_results_conn + gobject.io_add_watch(source, gobject.IO_IN, self.results_callback) - def apply_job_code(self, job_code, overwrite=True, to_all_rows=False, thread_id=None): - """ - Applies the Job code to the selected rows, or all rows if to_all_rows is True. + terminate_queue = Queue() + run_event = Event() + run_event.set() - If overwrite is True, then it will overwrite any existing job code. - """ - - def _apply_job_code(): - status = self.get_status(iter) - if status in [STATUS_DOWNLOAD_PENDING, STATUS_WARNING, STATUS_NOT_DOWNLOADED]: + return self._initiate_task(task, task_results_conn, task_process_conn, + terminate_queue, run_event) + + def _setup_pipe(self): + return Pipe(duplex=False) + + def _initiate_task(self, task, task_process_conn, terminate_queue, run_event): + logger.error("Implement child class method!") + + + def processes(self): + for i in range(len(self._processes)): + yield self._processes[i] + + def start(self): + self.paused = False + for scan in self.processes(): + run_event = scan[2] + if not run_event.is_set(): + run_event.set() - if mediaFile.isImage: - apply = rn.usesJobCode(self.rapidApp.prefs.image_rename) or rn.usesJobCode(self.rapidApp.prefs.subfolder) - else: - apply = rn.usesJobCode(self.rapidApp.prefs.video_rename) or rn.usesJobCode(self.rapidApp.prefs.video_subfolder) - if apply: - if overwrite: - self.liststore.set(iter, 8, job_code) - mediaFile.jobcode = job_code - mediaFile.sampleStale = True - else: - if not self.get_job_code(iter): - self.liststore.set(iter, 8, job_code) - mediaFile.jobcode = job_code - mediaFile.sampleStale = True - else: - pass - #if they got an existing job code, may as well keep it there in case the user - #reactivates job codes again in their prefs - - if to_all_rows or thread_id is not None: - for iter in self.get_tree_row_iters(): - apply = True - if thread_id is not None: - t = self.get_thread(iter) - apply = t == thread_id - - if apply: - mediaFile = self.get_mediaFile(iter) - _apply_job_code() - if mediaFile.treerowref == self.previewed_file_treerowref: - self.show_preview(iter) - else: - for iter in self.get_tree_row_iters(selected_only = True): - mediaFile = self.get_mediaFile(iter) - _apply_job_code() - if mediaFile.treerowref == self.previewed_file_treerowref: - self.show_preview(iter) + def pause(self): + self.paused = True + for scan in self.processes(): + run_event = scan[2] + if run_event.is_set(): + run_event.clear() + + def _terminate_process(self, p): + self._send_termination_msg(p) + # The process might be paused: let it run + run_event = p[2] + if not run_event.is_set(): + run_event.set() - def job_code_missing(self, selected_only): + def _send_termination_msg(self, p): + p[1].put(None) + + def terminate_process(self, process_id): """ - Returns True if any of the pending downloads do not have a - job code assigned. - - If selected_only is True, will only check in rows that the - user has selected. + Send a signal to process with matching process_id that it should + immediately terminate """ - - def _job_code_missing(iter): - status = self.get_status(iter) - if status in [STATUS_WARNING, STATUS_NOT_DOWNLOADED]: - is_image = self.get_is_image(iter) - job_code = self.get_job_code(iter) - return needAJobCode.needAJobCode(job_code, is_image) - return False - - self._setUsesJobCode() - needAJobCode = NeedAJobCode(self.rapidApp.prefs) - - v = False - if selected_only: - selection = self.get_selection() - model, pathlist = selection.get_selected_rows() - for path in pathlist: - iter = self.liststore.get_iter(path) - v = _job_code_missing(iter) - if v: - break - else: - iter = self.liststore.get_iter_first() - while iter: - v = _job_code_missing(iter) - if v: - break - iter = self.liststore.iter_next(iter) - return v - + for p in self.processes(): + if p[0].pid == process_id: + if p[0].is_alive(): + self._terminate_process(p) - def _set_download_pending(self, iter, threads): - existing_status = self.get_status(iter) - if existing_status in [STATUS_WARNING, STATUS_NOT_DOWNLOADED]: - self.liststore.set(iter, 11, STATUS_DOWNLOAD_PENDING) - self.liststore.set(iter, 10, self.download_pending_icon) - # this value is in a thread's list of files to download - mediaFile = self.get_mediaFile(iter) - # each thread will see this change in status - mediaFile.status = STATUS_DOWNLOAD_PENDING - thread = self.get_thread(iter) - if thread not in threads: - threads.append(thread) - - def set_status_to_download_pending(self, selected_only, thread_id=None): + def request_termination(self): """ - Sets status of files to be download pending, if they are waiting to be downloaded - if selected_only is true, only applies to selected rows - - If thread_id is not None, then after the statuses have been set, - the thread will be restarted (this is intended for the cases - where this method is called from a thread and auto start is True) + Send a signal to processes that they should immediately terminate + """ + requested = False + for p in self.processes(): + if p[0].is_alive(): + requested = True + self._terminate_process(p) + + return requested + + def terminate_forcefully(self): + """ + Forcefully terminates any running processes. Use with great caution. + No cleanup action is performed. - Returns a list of threads which can be downloaded + As python essential reference (4th edition) says, if the process + 'holds a lock or is involved with interprocess communication, + terminating it might cause a deadlock or corrupted I/O.' """ - threads = [] - if selected_only: - for iter in self.get_tree_row_iters(selected_only = True): - self._set_download_pending(iter, threads) - else: - for iter in self.get_tree_row_iters(): - apply = True - if thread_id is not None: - t = self.get_thread(iter) - apply = t == thread_id - if apply: - self._set_download_pending(iter, threads) - - if thread_id is not None: - # restart the thread - workers[thread_id].startStop() - return threads - - def update_status_post_download(self, treerowref): - path = treerowref.get_path() - if not path: - sys.stderr.write("FIXME: SelectionTreeView treerowref no longer refers to valid row\n") - else: - iter = self.liststore.get_iter(path) - mediaFile = self.get_mediaFile(iter) - status = mediaFile.status - self.liststore.set(iter, 11, status) - self.liststore.set(iter, 10, self.get_status_icon(status)) + for p in self.processes(): + if p[0].is_alive(): + logger.info("Forcefully terminating %s in %s" , p[0].name, + self.__class__.__name__) + p[0].terminate() + - # If this row is currently previewed, then should update the preview - if mediaFile.treerowref == self.previewed_file_treerowref: - self.show_preview(iter) + def get_pipe(self, source): + return self._pipes[source] + + def get_no_active_processes(self): + """ + Returns how many processes are currently active, i.e. running + """ + i = 0 + for p in self.processes(): + if p[0].is_alive(): + i += 1 + return i -class SelectionVBox(gtk.VBox): +class ScanManager(TaskManager): + + def __init__(self, results_callback, batch_size, generate_folder, + add_device_function): + TaskManager.__init__(self, results_callback, batch_size) + self.add_device_function = add_device_function + self.generate_folder = generate_folder + + def _initiate_task(self, device, task_results_conn, task_process_conn, + terminate_queue, run_event): + + scan = scan_process.Scan(device.get_path(), self.batch_size, self.generate_folder, + task_process_conn, terminate_queue, run_event) + scan.start() + self._processes.append((scan, terminate_queue, run_event)) + self.add_device_function(scan.pid, device, + # This refers to when a device like a hard drive is having its contents scanned, + # looking for photos or videos. It is visible initially in the progress bar for each device + # (which normally holds "x photos and videos"). + # It maybe displayed only briefly if the contents of the device being scanned is small. + progress_bar_text=_('scanning...')) + + return scan.pid + +class CopyFilesManager(TaskManager): + + def _initiate_task(self, task, task_results_conn, + task_process_conn, terminate_queue, run_event): + photo_download_folder = task[0] + video_download_folder = task[1] + scan_pid = task[2] + files = task[3] + + copy_files = copyfiles.CopyFiles(photo_download_folder, + video_download_folder, + files, + scan_pid, self.batch_size, + task_process_conn, terminate_queue, run_event) + copy_files.start() + self._processes.append((copy_files, terminate_queue, run_event)) + return copy_files.pid + +class ThumbnailManager(TaskManager): + def _initiate_task(self, task, task_results_conn, + task_process_conn, terminate_queue, run_event): + scan_pid = task[0] + files = task[1] + generator = tn.GenerateThumbnails(scan_pid, files, self.batch_size, + task_process_conn, terminate_queue, + run_event) + generator.start() + self._processes.append((generator, terminate_queue, run_event)) + return generator.pid + +class BackupFilesManager(TaskManager): """ - Dialog from which the user can select photos and videos to download + Handles backup processes. This is a little different from other Task + Manager classes in that its pipe is Duplex, and the work done by it + is not pre-assigned when the process is started. """ + def __init__(self, results_callback, batch_size): + TaskManager.__init__(self, results_callback, batch_size) + self.backup_devices_by_path = {} - - def __init__(self, parentApp): - """ - Initialize values for log dialog, but do not display. - """ + def _setup_pipe(self): + return Pipe(duplex=True) - gtk.VBox.__init__(self) - self.parentApp = parentApp + def _send_termination_msg(self, p): + p[1].put(None) + p[3].send((None, None, None, None)) - tiny_screen = TINY_SCREEN - if tiny_screen: - config.max_thumbnail_size = 160 + def _initiate_task(self, task, task_results_conn, task_process_conn, + terminate_queue, run_event): + path = task[0] + name = task[1] + backup_files = backupfile.BackupFiles(path, name, self.batch_size, + task_process_conn, terminate_queue, + run_event) + backup_files.start() + self._processes.append((backup_files, terminate_queue, run_event, + task_results_conn)) - selection_scrolledwindow = gtk.ScrolledWindow() - selection_scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - selection_viewport = gtk.Viewport() + self.backup_devices_by_path[path] = (task_results_conn, backup_files.pid) + return backup_files.pid - self.selection_treeview = SelectionTreeView(self) + def backup_file(self, move_succeeded, rpd_file, path_suffix, + backup_duplicate_overwrite): + for path in self.backup_devices_by_path: + task_results_conn = self.backup_devices_by_path[path][0] + task_results_conn.send((move_succeeded, rpd_file, path_suffix, + backup_duplicate_overwrite)) + + def add_device(self, path, name): + """ + Convenience function to setup adding a backup device + """ + return self.add_task((path, name)) + + def remove_device(self, path): + pid = self.backup_devices_by_path[path][1] + self.terminate_process(pid) + del self.backup_devices_by_path[path] - selection_scrolledwindow.add(self.selection_treeview) - - - # Job code controls - self.add_job_code_combo() - left_pane_vbox = gtk.VBox(spacing = 12) - left_pane_vbox.pack_start(selection_scrolledwindow, True, True) - left_pane_vbox.pack_start(self.job_code_hbox, False, True) - # Window sizes - #selection_scrolledwindow.set_size_request(350, -1) - - - # Preview pane - - # Zoom in and out slider (make the image bigger / smaller) - - # Zoom out (on the left of the slider) - self.zoom_out_eventbox = gtk.EventBox() - self.zoom_out_eventbox.set_events(gtk.gdk.BUTTON_PRESS_MASK) - self.zoom_out_image = gtk.Image() - self.zoom_out_image.set_from_file(paths.share_dir('glade3/zoom-out.png')) - self.zoom_out_eventbox.add(self.zoom_out_image) - self.zoom_out_eventbox.connect("button_press_event", self.zoom_out_0_callback) - - # Zoom in (on the right of the slider) - self.zoom_in_eventbox = gtk.EventBox() - self.zoom_in_eventbox.set_events(gtk.gdk.BUTTON_PRESS_MASK) - self.zoom_in_image = gtk.Image() - self.zoom_in_image.set_from_file(paths.share_dir('glade3/zoom-in.png')) - self.zoom_in_eventbox.add(self.zoom_in_image) - self.zoom_in_eventbox.connect("button_press_event", self.zoom_in_100_callback) - - self.slider_adjustment = gtk.Adjustment(value=self.parentApp.prefs.preview_zoom, - lower=config.MIN_THUMBNAIL_SIZE, upper=config.max_thumbnail_size, - step_incr=1.0, page_incr=config.THUMBNAIL_INCREMENT, page_size=0) - self.slider_adjustment.connect("value_changed", self.resize_image_callback) - self.slider_hscale = gtk.HScale(self.slider_adjustment) - self.slider_hscale.set_draw_value(False) # don't display numeric value - self.slider_hscale.set_size_request(config.MIN_THUMBNAIL_SIZE * 2, -1) +class SingleInstanceTaskManager: + """ + Base class to manage single instance processes. Examples are daemon + processes, but also a non-daemon process that has one simple task. + + Core (infrastructure) functionality is implemented in this class. + Derived classes should implemented functionality to actually implement + specific tasks. + """ + def __init__(self, results_callback): + self.results_callback = results_callback + self.task_results_conn, self.task_process_conn = Pipe(duplex=True) - #Preview image - self.base_preview_image = None # large size image used to scale down from - self.preview_image = gtk.Image() + source = self.task_results_conn.fileno() + gobject.io_add_watch(source, gobject.IO_IN, self.task_results) - self.preview_image.set_alignment(0, 0.5) - #leave room for thumbnail shadow - if DROP_SHADOW: - self.cacheDropShadow() - else: - self.shadow_size = 0 - image_size, shadow_size, offset = self._imageAndShadowSize() +class PreviewManager(SingleInstanceTaskManager): + def __init__(self, results_callback): + SingleInstanceTaskManager.__init__(self, results_callback) + self._get_preview = tn.GetPreviewImage(self.task_process_conn) + self._get_preview.start() - self.preview_image.set_size_request(image_size, image_size) + def get_preview(self, unique_id, full_file_name, file_type, size_max): + self.task_results_conn.send((unique_id, full_file_name, file_type, size_max)) - #labels to display file information + def task_results(self, source, condition): + unique_id, preview_full_size, preview_small = self.task_results_conn.recv() + self.results_callback(unique_id, preview_full_size, preview_small) + return True - #Original filename - self.preview_original_name_label = gtk.Label() - self.preview_original_name_label.set_alignment(0, 0.5) - self.preview_original_name_label.set_ellipsize(pango.ELLIPSIZE_END) +class SubfolderFileManager(SingleInstanceTaskManager): + """ + Manages the daemon process that renames files and creates subfolders + """ + def __init__(self, results_callback, sequence_values): + SingleInstanceTaskManager.__init__(self, results_callback) + self._subfolder_file = subfolderfile.SubfolderFile(self.task_process_conn, sequence_values) + self._subfolder_file.start() + logger.debug("SubfolderFile PID: %s", self._subfolder_file.pid) + + def rename_file_and_move_to_subfolder(self, download_succeeded, + download_count, rpd_file): + + self.task_results_conn.send((download_succeeded, download_count, + rpd_file)) + logger.debug("Download count: %s.", download_count) + + + def task_results(self, source, condition): + move_succeeded, rpd_file = self.task_results_conn.recv() + self.results_callback(move_succeeded, rpd_file) + return True +class ResizblePilImage(gtk.DrawingArea): + def __init__(self, bg_color=None): + gtk.DrawingArea.__init__(self) + self.base_image = None + self.bg_color = bg_color + self.connect('expose_event', self.expose) - #Device (where it will be downloaded from) - self.preview_device_expander = gtk.Expander() - self.preview_device_label = gtk.Label() - self.preview_device_label.set_alignment(0, 0.5) - self.preview_device_image = gtk.Image() + def set_image(self, image): + self.base_image = image - self.preview_device_path_label = gtk.Label() - self.preview_device_path_label.set_alignment(0, 0.5) - self.preview_device_path_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - self.preview_device_path_label.set_padding(30, 0) - self.preview_device_expander.add(self.preview_device_path_label) + #set up sizes and ratio used for drawing the derived image + self.base_image_w = self.base_image.size[0] + self.base_image_h = self.base_image.size[1] + self.base_image_aspect = float(self.base_image_w) / self.base_image_h - device_hbox = gtk.HBox(False, spacing = 6) - device_hbox.pack_start(self.preview_device_image) - device_hbox.pack_start(self.preview_device_label, True, True) + self.queue_draw() - self.preview_device_expander.set_label_widget(device_hbox) + def expose(self, widget, event): + + cairo_context = self.window.cairo_create() - #Filename that has been generated - self.preview_name_label = gtk.Label() - self.preview_name_label.set_alignment(0, 0.5) - self.preview_name_label.set_ellipsize(pango.ELLIPSIZE_END) + x = event.area.x + y = event.area.y + w = event.area.width + h = event.area.height - #Download destination - self.preview_destination_expander = gtk.Expander() - self.preview_destination_label = gtk.Label() - self.preview_destination_label.set_alignment(0, 0.5) - self.preview_destination_image = gtk.Image() + #constrain operations to event area + cairo_context.rectangle(x, y, w, h) + cairo_context.clip_preserve() - self.preview_destination_path_label = gtk.Label() - self.preview_destination_path_label.set_alignment(0, 0.5) - self.preview_destination_path_label.set_ellipsize(pango.ELLIPSIZE_MIDDLE) - self.preview_destination_path_label.set_padding(30, 0) - self.preview_destination_expander.add(self.preview_destination_path_label) + #set background color, if needed + if self.bg_color: + cairo_context.set_source_rgb(*self.bg_color) + cairo_context.fill_preserve() - destination_hbox = gtk.HBox(False, spacing = 6) - destination_hbox.pack_start(self.preview_destination_image) - destination_hbox.pack_start(self.preview_destination_label, True, True) + if not self.base_image: + return False + + frame_aspect = float(w) / h - self.preview_destination_expander.set_label_widget(destination_hbox) + if frame_aspect > self.base_image_aspect: + # Frame is wider than image + height = h + width = int(height * self.base_image_aspect) + else: + # Frame is taller than image + width = w + height = int(width / self.base_image_aspect) + + #resize image + pil_image = self.base_image.copy() + if self.base_image_w < width or self.base_image_h < height: + logger.debug("Upsizing image") + pil_image = tn.upsize_pil(pil_image, (width, height)) + else: + logger.debug("Downsizing image") + tn.downsize_pil(pil_image, (width, height)) + #image width and height + image_w = pil_image.size[0] + image_h = pil_image.size[1] - #Status of the file + #center the image horizontally and vertically + #top left and right corners for the image: + image_x = x + ((w - image_w) / 2) + image_y = y + ((h - image_h) / 2) - self.preview_status_icon = gtk.Image() - self.preview_status_icon.set_size_request(16,16) + image = create_cairo_image_surface(pil_image, image_w, image_h) + cairo_context.set_source_surface(image, image_x, image_y) + cairo_context.paint() - self.preview_status_label = gtk.Label() - self.preview_status_label.set_alignment(0, 0.5) - self.preview_status_label.set_ellipsize(pango.ELLIPSIZE_END) - self.preview_status_label.set_padding(12, 0) - - #Title of problems encountered in generating the name / subfolder - self.preview_problem_title_label = gtk.Label() - self.preview_problem_title_label.set_alignment(0, 0.5) - self.preview_problem_title_label.set_ellipsize(pango.ELLIPSIZE_END) - self.preview_problem_title_label.set_padding(12, 0) + return False + - #Details of what the problem(s) are - self.preview_problem_label = gtk.Label() - self.preview_problem_label.set_alignment(0, 0) - self.preview_problem_label.set_line_wrap(True) - self.preview_problem_label.set_padding(12, 0) - #Can't combine wrapping and ellipsize, sadly - #self.preview_problem_label.set_ellipsize(pango.ELLIPSIZE_END) - - #Put content into table - # Use a table so we can do the Gnome HIG layout more easily - self.preview_table = gtk.Table(10, 4) - self.preview_table.set_row_spacings(12) - left_spacer = gtk.Label('') - left_spacer.set_padding(12, 0) - right_spacer = gtk.Label('') - right_spacer.set_padding(6, 0) - - - spacer2 = gtk.Label('') - - #left and right spacers - self.preview_table.attach(left_spacer, 0, 1, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK) - self.preview_table.attach(right_spacer, 3, 4, 1, 2, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK) - - row = 0 - zoom_hbox = gtk.HBox() - zoom_hbox.pack_start(self.zoom_out_eventbox, False, False) - zoom_hbox.pack_start(self.slider_hscale, False, False) - zoom_hbox.pack_start(self.zoom_in_eventbox, False, False) - - self.preview_table.attach(zoom_hbox, 1, 3, row, row+1, yoptions=gtk.SHRINK) - - row += 1 - self.preview_table.attach(self.preview_image, 1, 3, row, row+1, yoptions=gtk.SHRINK) - row += 1 - - self.preview_table.attach(self.preview_original_name_label, 1, 3, row, row+1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.SHRINK) - row += 1 - if not tiny_screen: - self.preview_table.attach(self.preview_device_expander, 1, 3, row, row+1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.SHRINK) - row += 1 - - self.preview_table.attach(self.preview_name_label, 1, 3, row, row+1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.SHRINK) - row += 1 - if not tiny_screen: - self.preview_table.attach(self.preview_destination_expander, 1, 3, row, row+1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.SHRINK) - row += 1 - - if not tiny_screen: - self.preview_table.attach(spacer2, 0, 7, row, row+1, yoptions=gtk.SHRINK) - row += 1 - - self.preview_table.attach(self.preview_status_icon, 1, 2, row, row+1, xoptions=gtk.SHRINK, yoptions=gtk.SHRINK) - self.preview_table.attach(self.preview_status_label, 2, 3, row, row+1, yoptions=gtk.SHRINK) - row += 1 - - self.preview_table.attach(self.preview_problem_title_label, 2, 3, row, row+1, yoptions=gtk.SHRINK) - row += 1 - self.preview_table.attach(self.preview_problem_label, 2, 4, row, row+1, xoptions=gtk.EXPAND|gtk.FILL, yoptions=gtk.EXPAND|gtk.FILL) - row += 1 - - self.file_hpaned = gtk.HPaned() - self.file_hpaned.pack1(left_pane_vbox, shrink=False) - self.file_hpaned.pack2(self.preview_table, resize=True, shrink=False) - self.pack_start(self.file_hpaned, True, True) - if self.parentApp.prefs.hpaned_pos > 0: - self.file_hpaned.set_position(self.parentApp.prefs.hpaned_pos) - else: - # this is what the user will see the first time they run the app - self.file_hpaned.set_position(300) - self.show_all() - +class PreviewImage: - def set_base_preview_image(self, pixbuf): - """ - sets the unscaled pixbuf image to be displayed to the user - the actual image the user will see will depend on the scale - they've set to view it at - """ - self.base_preview_image = pixbuf + def __init__(self, parent_app, builder): + #set background color to equivalent of '#444444 + self.preview_image = ResizblePilImage(bg_color=(0.267, 0.267, 0.267)) + self.preview_image_eventbox = builder.get_object("preview_eventbox") + self.preview_image_eventbox.add(self.preview_image) + self.preview_image.show() + self.download_this_checkbutton = builder.get_object("download_this_checkbutton") + self.rapid_app = parent_app - def zoom_in(self): - self.slider_adjustment.set_value(min([config.max_thumbnail_size, int(self.slider_adjustment.get_value()) + config.THUMBNAIL_INCREMENT])) + self.base_preview_image = None # large size image used to scale down from + self.current_preview_size = (0,0) + self.preview_image_size_limit = (0,0) - def zoom_out(self): - self.slider_adjustment.set_value(max([config.MIN_THUMBNAIL_SIZE, int(self.slider_adjustment.get_value()) - config.THUMBNAIL_INCREMENT])) - - def zoom_in_100_callback(self, widget, value): - self.slider_adjustment.set_value(config.max_thumbnail_size) + self.unique_id = None - def zoom_out_0_callback(self, widget, value): - self.slider_adjustment.set_value(config.MIN_THUMBNAIL_SIZE) - - def set_display_preview_folders(self, value): - if value and self.selection_treeview.previewed_file_treerowref: - self.preview_destination_expander.show() - self.preview_device_expander.show() - - else: - self.preview_destination_expander.hide() - self.preview_device_expander.hide() - - def cacheDropShadow(self): - i, self.shadow_size, offset_v = self._imageAndShadowSize() - self.drop_shadow = DropShadow(offset=(offset_v,offset_v), shadow = (0x44, 0x44, 0x44, 0xff), border=self.shadow_size, trim_border = True) - - def _imageAndShadowSize(self): - image_size = int(self.slider_adjustment.get_value()) - offset_v = max([image_size / 25, 5]) # realistically size the shadow based on the size of the image - shadow_size = offset_v + 3 - image_size = image_size + offset_v * 2 + 3 - return (image_size, shadow_size, offset_v) - - def resize_image_callback(self, adjustment): - """ - Resize the preview image after the adjustment value has been - changed - """ - size = int(adjustment.value) - self.parentApp.prefs.preview_zoom = size - self.cacheDropShadow() - - pixbuf = self.scaledPreviewImage() - if pixbuf: - self.preview_image.set_from_pixbuf(pixbuf) - size = max([pixbuf.get_width(), pixbuf.get_height()]) - self.preview_image.set_size_request(size, size) - else: - self.preview_image.set_size_request(size + self.shadow_size, size + self.shadow_size) - - def scaledPreviewImage(self): + def set_preview_image(self, unique_id, pil_image, include_checkbutton_visible=None, + checked=None): """ - Generate a scaled version of the preview image """ - size = int(self.slider_adjustment.get_value()) - if not self.base_preview_image: - return None - else: - pixbuf = common.scale2pixbuf(size, size, self.base_preview_image) - - if DROP_SHADOW: - pil_image = pixbuf_to_image(pixbuf) - pil_image = self.drop_shadow.dropShadow(pil_image) - pixbuf = image_to_pixbuf(pil_image) - - return pixbuf - - def set_job_code_display(self): - """ - Shows or hides the job code entry + self.preview_image.set_image(pil_image) + self.unique_id = unique_id + if checked is not None: + self.download_this_checkbutton.set_active(checked) + self.download_this_checkbutton.grab_focus() + + if include_checkbutton_visible is not None: + self.download_this_checkbutton.props.visible = include_checkbutton_visible - If user is not using job codes in their file or subfolder names - then do not prompt for it - """ + def update_preview_image(self, unique_id, pil_image): + if unique_id == self.unique_id: + self.set_preview_image(unique_id, pil_image) + - if self.parentApp.needJobCodeForRenaming(): - self.job_code_hbox.show() - self.job_code_label.show() - self.job_code_combo.show() - self.selection_treeview.job_code_column.set_visible(True) - else: - self.job_code_hbox.hide() - self.job_code_label.hide() - self.job_code_combo.hide() - self.selection_treeview.job_code_column.set_visible(False) - - def update_job_code_combo(self): - # delete existing rows - while len(self.job_code_combo.get_model()) > 0: - self.job_code_combo.remove_text(0) - # add new ones - for text in self.parentApp.prefs.job_codes: - self.job_code_combo.append_text(text) - # clear existing entry displayed in entry box - self.job_code_entry.set_text('') +class RapidApp(dbus.service.Object): + """ + The main Rapid Photo Downloader application class. - def add_job_code_combo(self): - self.job_code_hbox = gtk.HBox(spacing = 12) - self.job_code_hbox.set_no_show_all(True) - self.job_code_label = gtk.Label(_("Job Code:")) - - self.job_code_combo = gtk.combo_box_entry_new_text() - for text in self.parentApp.prefs.job_codes: - self.job_code_combo.append_text(text) - - # make entry box have entry completion - self.job_code_entry = self.job_code_combo.child - - self.completion = gtk.EntryCompletion() - self.completion.set_match_func(self.job_code_match_func) - self.completion.connect("match-selected", - self.on_job_code_combo_completion_match) - self.completion.set_model(self.job_code_combo.get_model()) - self.completion.set_text_column(0) - self.job_code_entry.set_completion(self.completion) - - - self.job_code_combo.connect('changed', self.on_job_code_resp) - - self.job_code_entry.connect('activate', self.on_job_code_entry_resp) - - self.job_code_combo.set_tooltip_text(_("Enter a new Job Code and press Enter, or select an existing Job Code")) - - #add widgets - self.job_code_hbox.pack_start(self.job_code_label, False, False) - self.job_code_hbox.pack_start(self.job_code_combo, True, True) - self.set_job_code_display() - - def job_code_match_func(self, completion, key, iter): - model = completion.get_model() - return model[iter][0].lower().startswith(self.job_code_entry.get_text().lower()) - - def on_job_code_combo_completion_match(self, completion, model, iter): - self.job_code_entry.set_text(model[iter][0]) - self.job_code_entry.set_position(-1) - - def on_job_code_resp(self, widget): - """ - When the user has clicked on an existing job code - """ + Contains functionality for main program window, and directs all other + processes. + """ + + def __init__(self, bus, path, name, taskserver=None): - # ignore changes because the user is typing in a new value - if widget.get_active() >= 0: - self.job_code_chosen(widget.get_active_text()) - - def on_job_code_entry_resp(self, widget): - """ - When the user has hit enter after entering a new job code - """ - self.job_code_chosen(widget.get_text()) + dbus.service.Object.__init__ (self, bus, path, name) + self.running = False - def job_code_chosen(self, job_code): - """ - The user has selected a Job code, apply it to selected images. - """ - self.selection_treeview.apply_job_code(job_code, overwrite = True) - self.completion.set_model(None) - self.parentApp.assignJobCode(job_code) - self.completion.set_model(self.job_code_combo.get_model()) - - def add_file(self, mediaFile): - self.selection_treeview.add_file(mediaFile) - + self.taskserver = taskserver -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. - """ + # Setup program preferences, and set callback for when they change + self._init_prefs() - gnomeglade.Component.__init__(self, - paths.share_dir(config.GLADE_FILE), - "logdialog") - + # Initialize widgets in the main window, and variables that point to them + self._init_widgets() + self._init_pynotify() - self.widget.connect("delete-event", self.hide_window) + # Initialize job code handling + self._init_job_code() - self.parentApp = parentApp - self.log_textview.set_cursor_visible(False) - self.textbuffer = self.log_textview.get_buffer() + # Remember the window size from the last time the program was run, or + # set a default size + self._set_window_size() - self.errorTag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD, foreground="red") - self.warningTag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD) - self.resolutionTag = self.textbuffer.create_tag(style=pango.STYLE_ITALIC) + # Setup various widgets + self._setup_buttons() + self._setup_error_icons() + self._setup_icons() + + # Show the main window + self.rapidapp.show() - 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() - self.parentApp.warning_vseparator.show() + # Check program preferences - don't allow auto start if there is a problem + prefs_valid, msg = prefsrapid.check_prefs_for_validity(self.prefs) + if not prefs_valid: + self.notify_prefs_are_invalid(details=msg) - iter = self.textbuffer.get_end_iter() - if severity in [config.CRITICAL_ERROR, config.SERIOUS_ERROR]: - self.textbuffer.insert_with_tags(iter, problem +"\n", self.errorTag) - else: - self.textbuffer.insert_with_tags(iter, problem +"\n", self.warningTag) - if details: - 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.warning_vseparator.hide() - self.parentApp.prefs.show_log_dialog = False - self.widget.hide() - return True - - def hide_window(self, window, event): - window.hide() - return True + # Initialize variables with which to track important downloads results + self._init_download_tracking() + + # Set up process managers. + # A task such as scanning a device or copying files is handled in its + # own process. + self._start_process_managers() + + # Setup devices from which to download from and backup to + self.setup_devices(on_startup=True, on_preference_change=False, + block_auto_start=not prefs_valid) + + # Ensure the device collection scrolled window is not too small + self._set_device_collection_size() + + def on_rapidapp_destroy(self, widget, data=None): + self._terminate_processes(terminate_file_copies = True) + # save window and component sizes + self.prefs.vpaned_pos = self.main_vpaned.get_position() -class RapidApp(gnomeglade.GnomeApp, dbus.service.Object): - def __init__(self, bus, path, name): + x, y, width, height = self.rapidapp.get_allocation() + self.prefs.main_window_size_x = width + self.prefs.main_window_size_y = height - dbus.service.Object.__init__ (self, bus, path, name) - self.running = False + self.prefs.set_downloads_today_from_tracker(self.downloads_today_tracker) - gladefile = paths.share_dir(config.GLADE_FILE) - - gnomeglade.GnomeApp.__init__(self, "rapid", __version__, gladefile, "rapidapp") - - # notifications - self.displayDownloadSummaryNotification = False - self.initPyNotify() + gtk.main_quit() - self.prefs = RapidPreferences() - self.prefs.notify_add(self.on_preference_changed) + def _terminate_processes(self, terminate_file_copies=False): - self.testing = False - if self.testing: - self.setTestingEnv() - -# sys.exit(0) + if terminate_file_copies: + logger.info("Terminating all processes...") - # remember the window size from the last time the program was run - if self.prefs.main_window_maximized: - self.rapidapp.maximize() - elif self.prefs.main_window_size_x > 0: - self.rapidapp.set_default_size(self.prefs.main_window_size_x, self.prefs.main_window_size_y) + scan_termination_requested = self.scan_manager.request_termination() + thumbnails_termination_requested = self.thumbnails.thumbnail_manager.request_termination() + backup_termination_requested = self.backup_manager.request_termination() + + if terminate_file_copies: + copy_files_termination_requested = self.copy_files_manager.request_termination() else: - # set a default size - self.rapidapp.set_default_size(650, 650) - - if gtk.gdk.screen_height() <= config.TINY_SCREEN_HEIGHT: - self.prefs.display_preview_folders = False - self.menu_preview_folders.set_sensitive(False) - - self.widget.show() + copy_files_termination_requested = False - self._setupIcons() + if (scan_termination_requested or thumbnails_termination_requested or + backup_termination_requested): + time.sleep(1) + if (self.scan_manager.get_no_active_processes() > 0 or + self.thumbnails.thumbnail_manager.get_no_active_processes() > 0 or + self.backup_manager.get_no_active_processes() > 0): + time.sleep(1) + # must try again, just in case a new scan has meanwhile started! + self.scan_manager.request_termination() + self.thumbnails.thumbnail_manager.terminate_forcefully() + self.scan_manager.terminate_forcefully() + self.backup_manager.terminate_forcefully() + + if terminate_file_copies and copy_files_termination_requested: + time.sleep(1) + self.copy_files_manager.terminate_forcefully() - # this must come after the window is shown - if self.prefs.vpaned_pos > 0: - self.main_vpaned.set_position(self.prefs.vpaned_pos) - else: - self.main_vpaned.set_position(66) + if terminate_file_copies: + self._clean_all_temp_dirs() - self.checkIfFirstTimeProgramEverRun() + # # # + # Events and tasks related to displaying preview images and thumbnails + # # # - displayPreferences = self.checkForUpgrade(__version__) - self.prefs.program_version = __version__ + def on_download_this_checkbutton_toggled(self, checkbutton): + value = checkbutton.get_active() + self.thumbnails.set_selected(self.preview_image.unique_id, value) + self.set_download_action_sensitivity() + + def on_preview_eventbox_button_press_event(self, widget, event): - self.timeRemaining = TimeRemaining() - self._resetDownloadInfo() - self.statusbar_context_id = self.rapid_statusbar.get_context_id("progress") + if event.type == gtk.gdk._2BUTTON_PRESS and event.button == 1: + self.show_thumbnails() + + def on_show_thumbnails_action_activate(self, action): + logger.debug("on_show_thumbnails_action_activate") + self.show_thumbnails() - # hide display of warning and error symbols in the taskbar until they are needed - self.error_image.hide() - self.warning_image.hide() - self.warning_vseparator.hide() + def on_show_image_action_activate(self, action): + logger.debug("on_show_image_action_activate") + self.thumbnails.show_preview() - if not displayPreferences: - displayPreferences = not self.checkPreferencesOnStartup() + def on_check_all_action_activate(self, action): + self.thumbnails.check_all(check_all=True) - # display download information using threads - global media_collection_treeview, log_dialog - global workers + def on_uncheck_all_action_activate(self, action): + self.thumbnails.check_all(check_all=False) - #track files that should have a suffix added to them - global duplicate_files + def on_check_all_photos_action_activate(self, action): + self.thumbnails.check_all(check_all=True, + file_type=rpdfile.FILE_TYPE_PHOTO) - #track files that have been downloaded in this session - global downloaded_files + def on_check_all_videos_action_activate(self, action): + self.thumbnails.check_all(check_all=True, + file_type=rpdfile.FILE_TYPE_VIDEO) + + def on_quit_action_activate(self, action): + self.on_rapidapp_destroy(widget=self.rapidapp, data=None) - # control sequence numbers and letters - global sequences + def on_refresh_action_activate(self, action): + self.setup_devices(on_startup=False, on_preference_change=False, + block_auto_start=True) + + def on_get_help_action_activate(self, action): + webbrowser.open("http://www.damonlynch.net/rapid/help.html") - # whether we need to prompt for a job code - global need_job_code_for_renaming - - duplicate_files = {} - downloaded_files = DownloadedFiles() + def on_about_action_activate(self, action): + self.about.set_property("name", PROGRAM_NAME) + self.about.set_property("version", utilities.human_readable_version( + __version__)) + self.about.run() + self.about.destroy() + + def on_report_problem_action_activate(self, action): + webbrowser.open("https://bugs.launchpad.net/rapid") + + def on_translate_action_activate(self, action): + webbrowser.open("http://www.damonlynch.net/rapid/translate.html") + + def on_donate_action_activate(self, action): + webbrowser.open("http://www.damonlynch.net/rapid/donate.html") + + def show_preview_image(self, unique_id, image, include_checkbutton_visible, checked): + if self.main_notebook.get_current_page() == 0: # thumbnails + logger.debug("Switching to preview image display") + self.main_notebook.set_current_page(1) + self.preview_image.set_preview_image(unique_id, image, include_checkbutton_visible, checked) + self.next_image_action.set_sensitive(True) + self.prev_image_action.set_sensitive(True) - self.download_start_time = None + def update_preview_image(self, unique_id, image): + self.preview_image.update_preview_image(unique_id, image) - downloadsToday = self.prefs.getAndMaybeResetDownloadsToday() - sequences = rn.Sequences(downloadsToday, self.prefs.stored_sequence_no) + def show_thumbnails(self): + logger.debug("Switching to thumbnails display") + self.main_notebook.set_current_page(0) + self.thumbnails.select_image(self.preview_image.unique_id) + self.next_image_action.set_sensitive(False) + self.prev_image_action.set_sensitive(False) - 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() - self.downloadedFilesLock = Lock() - - # log window, in dialog format - # used for displaying download information to the user + def on_next_image_action_activate(self, action): + if self.preview_image.unique_id is not None: + self.thumbnails.show_next_image(self.preview_image.unique_id) + + def on_prev_image_action_activate(self, action): + if self.preview_image.unique_id is not None: + self.thumbnails.show_prev_image(self.preview_image.unique_id) - log_dialog = LogDialog(self) + def set_thumbnail_sort(self): + """ + If all the scans are complete, sets the sort order + """ + if self.scan_manager.get_no_active_processes() == 0: + self.thumbnails.sort_by_timestamp() - self.volumeMonitor = None - if self.usingVolumeMonitor(): - self.startVolumeMonitor() + # # # + # Volume management + # # # + + def start_volume_monitor(self): + if not self.vmonitor: + self.vmonitor = gio.volume_monitor_get() + self.vmonitor.connect("mount-added", self.on_mount_added) + self.vmonitor.connect("mount-removed", self.on_mount_removed) + + + def _backup_device_name(self, path): + if self.backup_devices[path] is None: + name = path + else: + name = self.backup_devices[path].get_name() + return name - # flag to indicate whether the user changed some preferences that - # indicate the image and backup devices should be setup again - self.rerunSetupAvailableImageAndVideoMedia = False - self.rerunSetupAvailableBackupMedia = False + def setup_devices(self, on_startup, on_preference_change, block_auto_start): + """ - # flag to indicate the user changes some preferences and the display - # of sample names and subfolders needs to be refreshed - self.refreshGeneratedSampleSubfolderAndName = False + Setup devices from which to download from and backup to - # counter to indicate how many threads need their sample names and subfolders regenerated because the user - # changes their prefs at the same time as devices were being scanned - self.noAfterScanRefreshGeneratedSampleSubfolderAndName = 0 + Sets up volumes for downloading from and backing up to - # flag to indicate the user changes some preferences and the display - # of sample download folders needs to be refreshed - self.refreshSampleDownloadFolder = False - self.noAfterScanRefreshSampleDownloadFolders = 0 + on_startup should be True if the program is still starting, + i.e. this is being called from the program's initialization. - # flag to indicate that the preferences dialog window is being - # displayed to the user - self.preferencesDialogDisplayed = False + on_preference_change should be True if this is being called as the + result of a preference being changed - # set up tree view display to display image devices and download status - media_collection_treeview = MediaTreeView(self) - - self.media_collection_vbox.pack_start(media_collection_treeview) + block_auto_start should be True if automation options to automatically + start a download should be ignored - #Selection display - self.selection_vbox = SelectionVBox(self) - self.selection_hbox.pack_start(self.selection_vbox, padding=12) - self.set_display_selection(self.prefs.display_selection) - self.set_display_preview_folders(self.prefs.display_preview_folders) + Removes any image media that are currently not downloaded, + or finished downloading + """ + + if self.using_volume_monitor(): + self.start_volume_monitor() - self.backupVolumes = {} - #Help button and download buttons - self._setupDownloadbuttons() + self.clear_non_running_downloads() - #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) + mounts = [] + self.backup_devices = {} + if self.using_volume_monitor(): + # either using automatically detected backup devices + # or download devices + for mount in self.vmonitor.get_mounts(): + if not mount.is_shadowed(): + path = mount.get_root().get_path() + if path: + if (path in self.prefs.device_blacklist and + self.search_for_PSD()): + logger.info("%s ignored", mount.get_name()) + else: + logger.info("Detected %s", mount.get_name()) + is_backup_mount = self.check_if_backup_mount(path) + if is_backup_mount: + self.backup_devices[path] = mount + elif (self.prefs.device_autodetection and + (dv.is_DCIM_device(path) or + self.search_for_PSD())): + mounts.append((path, mount)) + + + if not self.prefs.device_autodetection: + # user manually specified the path from which to download + path = self.prefs.device_location + if path: + logger.info("Using manually specified path %s", path) + if utilities.is_directory(path): + mounts.append((path, None)) + else: + logger.error("Download path does not exist: %s", path) - # menus - - #preview panes - self.menu_display_selection.set_active(self.prefs.display_selection) - self.menu_preview_folders.set_active(self.prefs.display_preview_folders) + if self.prefs.backup_images: + if not self.prefs.backup_device_autodetection: + # user manually specified backup location + # will backup to this path, but don't need any volume info + # associated with it + self.backup_devices[self.prefs.backup_location] = None + + for path in self.backup_devices: + name = self._backup_device_name(path) + self.backup_manager.add_device(path, name) + + self.update_no_backup_devices() - #preview columns in pane - if not DOWNLOAD_VIDEO: - self.menu_type_column.set_active(False) - self.menu_type_column.set_sensitive(False) + # Display amount of free space in a status bar message + self.display_free_space() + + if block_auto_start: + self.auto_start_is_on = False else: - self.menu_type_column.set_active(self.prefs.display_type_column) - self.menu_size_column.set_active(self.prefs.display_size_column) - self.menu_filename_column.set_active(self.prefs.display_filename_column) - self.menu_device_column.set_active(self.prefs.display_device_column) - self.menu_path_column.set_active(self.prefs.display_path_column) + self.auto_start_is_on = ((not on_preference_change) and + ((self.prefs.auto_download_at_startup and + on_startup) or + (self.prefs.auto_download_upon_device_insertion and + not on_startup))) - self.menu_clear.set_sensitive(False) - - need_job_code_for_renaming = self.needJobCodeForRenaming() - self.menu_select_all_without_job_code.set_sensitive(need_job_code_for_renaming) - self.menu_select_all_with_job_code.set_sensitive(need_job_code_for_renaming) + for m in mounts: + path, mount = m + device = dv.Device(path=path, mount=mount) + if (self.search_for_PSD() and + path not in self.prefs.device_whitelist): + # prompt user to see if device should be used or not + self.get_use_device(device) + else: + scan_pid = self.scan_manager.add_task(device) + if mount is not None: + self.mounts_by_path[path] = scan_pid + if not mounts: + self.set_download_action_sensitivity() - #job code initialization - self.last_chosen_job_code = None - self.prompting_for_job_code = False + def get_use_device(self, device): + """ Prompt user whether or not to download from this device """ + + logger.info("Prompting whether to use %s", device.get_name()) + d = dv.UseDeviceDialog(self.rapidapp, device, self.got_use_device) + + def got_use_device(self, dialog, user_selected, permanent_choice, device): + """ User has chosen whether or not to use a device to download from """ + dialog.destroy() - #check to see if the download folder exists and is writable - displayPreferences_2 = not self.checkDownloadPathOnStartup() - displayPreferences = displayPreferences or displayPreferences_2 + path = device.get_path() + + if user_selected: + if permanent_choice and path not in self.prefs.device_whitelist: + # do NOT do a list append operation here without the assignment, + # or the actual preferences will not be updated!! + if len(self.prefs.device_whitelist): + self.prefs.device_whitelist = self.prefs.device_whitelist + [path] + else: + self.prefs.device_whitelist = [path] + scan_pid = self.scan_manager.add_task(device) + self.mounts_by_path[path] = scan_pid - if self.prefs.device_autodetection == False: - displayPreferences_2 = not self.checkImageDevicePathOnStartup() - displayPreferences = displayPreferences or displayPreferences_2 + elif permanent_choice and path not in self.prefs.device_blacklist: + # do not do a list append operation here without the assignment, or the preferences will not be updated! + if len(self.prefs.device_blacklist): + self.prefs.device_blacklist = self.prefs.device_blacklist + [path] + else: + self.prefs.device_blacklist = [path] + + def search_for_PSD(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 check_if_backup_mount(self, path): + """ + Checks to see if backups are enabled and path represents a valid backup location - #setup download and backup mediums, initiating scans - self.setupAvailableImageAndBackupMedia(onStartup=True, onPreferenceChange=False, doNotAllowAutoStart = displayPreferences) + Checks against user preferences. + """ + identifiers = [self.prefs.backup_identifier] + if DOWNLOAD_VIDEO: + identifiers.append(self.prefs.video_backup_identifier) + if self.prefs.backup_images: + if self.prefs.backup_device_autodetection: + if dv.is_backup_media(path, identifiers): + return True + elif path == self.prefs.backup_location: + # user manually specified the path + return True + return False + + def update_no_backup_devices(self): + self.download_tracker.set_no_backup_devices(len(self.backup_devices)) - #adjust viewport size for displaying media - #this is important because the code in MediaTreeView.addCard() is inaccurate at program startup + def refresh_backup_media(self): + """ + Setup the backup media - if media_collection_treeview.mapThreadToRow: - height = self.media_collection_viewport.size_request()[1] - self.media_collection_scrolledwindow.set_size_request(-1, height) - else: - # don't allow the media collection to be absolutely empty - self.media_collection_scrolledwindow.set_size_request(-1, 47) + Assumptions: this is being called after the user has changed their + preferences AND download media has already been setup + """ - self.download_button.grab_default() - # for some reason, the grab focus command is not working... unsure why - self.download_button.grab_focus() + # terminate any running backup processes + self.backup_manager.request_termination() - if displayPreferences: - PreferencesDialog(self) + self.backup_devices = {} + if self.prefs.backup_images: + if not self.prefs.backup_device_autodetection: + # user manually specified backup location + # will backup to this path, but don't need any volume info associated with it + self.backup_devices[self.prefs.backup_location] = None + else: + for mount in self.vmonitor.get_mounts(): + if not mount.is_shadowed(): + path = mount.get_root().get_path() + if path: + if self.check_if_backup_mount(path): + # is a backup volume + if path not in self.backup_devices: + self.backup_devices[path] = mount + for path in self.backup_devices: + name = self._backup_device_name(path) + self.backup_manager.add_device(path, name) - - @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 -# if not using_gio: - self.main() -# else: -# mainloop = gobject.MainLoop() -# mainloop.run() - self.running = False + self.update_no_backup_devices() + self.display_free_space() - def setTestingEnv(self): - #self.prefs.program_version = '0.0.8~b7' - p = ['Date time', 'Image date', 'YYYYMMDD', 'Text', '-', '', 'Date time', 'Image date', 'HHMM', 'Text', '-', '', rn.SEQUENCES, rn.DOWNLOAD_SEQ_NUMBER, rn.SEQUENCE_NUMBER_3, 'Text', '-iso', '', 'Metadata', 'ISO', '', 'Text', '-f', '', 'Metadata', 'Aperture', '', 'Text', '-', '', 'Metadata', 'Focal length', '', 'Text', 'mm-', '', 'Metadata', 'Exposure time', '', 'Filename', 'Extension', 'lowercase'] - v = ['Date time', 'Video date', 'YYYYMMDD', 'Text', '-', '', 'Date time', 'Video date', 'HHMM', 'Text', '-', '', 'Sequences', 'Downloads today', 'One digit', 'Text', '-', '', 'Metadata', 'Width', '', 'Text', 'x', '', 'Metadata', 'Height', '', 'Filename', 'Extension', 'lowercase'] - f = '/home/damon/store/rapid-dump' - self.prefs.image_rename = p - self.prefs.video_rename = v - self.prefs.download_folder = f - self.prefs.video_download_folder = f - - - def _setupIcons(self): - icons = ['rapid-photo-downloader-downloaded', - 'rapid-photo-downloader-downloaded-with-error', - 'rapid-photo-downloader-downloaded-with-warning', - 'rapid-photo-downloader-download-pending', - 'rapid-photo-downloader-jobcode'] - - icon_list = [(icon, paths.share_dir('glade3/%s.svg' % icon)) for icon in icons] - common.register_iconsets(icon_list) - - def displayFreeSpace(self): + def using_volume_monitor(self): """ - Displays the amount of space free on the filesystem the files will be downloaded to. - Also displays backup volumes / path being used. + Returns True if programs needs to use gio volume monitor """ - msg = '' - if using_gio and os.path.isdir(self.prefs.download_folder): - folder = gio.File(self.prefs.download_folder) - fileInfo = folder.query_filesystem_info(gio.FILE_ATTRIBUTE_FILESYSTEM_FREE) - free = common.formatSizeForUser(fileInfo.get_attribute_uint64(gio.FILE_ATTRIBUTE_FILESYSTEM_FREE)) - msg = " " + _("%(free)s available") % {'free': free} + return (self.prefs.device_autodetection or + (self.prefs.backup_images and + self.prefs.backup_device_autodetection + )) + + def on_mount_added(self, vmonitor, mount): + """ + callback run when gio indicates a new volume + has been mounted + """ + + + if mount.is_shadowed(): + # ignore this type of mount + return - if self.prefs.backup_images: - if not self.prefs.backup_device_autodetection: - # user manually specified backup location - msg2 = _('Backing up to %(path)s') % {'path':self.prefs.backup_location} + path = mount.get_root().get_path() + if path is not None: + + if path in self.prefs.device_blacklist and self.search_for_PSD(): + logger.info("Device %(device)s (%(path)s) ignored" % { + 'device': mount.get_name(), 'path': path}) else: - msg2 = self.displayBackupVolumes() + is_backup_mount = self.check_if_backup_mount(path) + + if is_backup_mount: + if path not in self.backup_devices: + self.backup_devices[path] = mount + name = self._backup_device_name(path) + self.backup_manager.add_device(path, name) + self.update_no_backup_devices() + self.display_free_space() + + elif self.prefs.device_autodetection and (dv.is_DCIM_device(path) or + self.search_for_PSD()): + + self.auto_start_is_on = self.prefs.auto_download_upon_device_insertion + device = dv.Device(path=path, mount=mount) + if self.search_for_PSD() and path not in self.prefs.device_whitelist: + # prompt user if device should be used or not + self.get_use_device(device) + else: + scan_pid = self.scan_manager.add_task(device) + self.mounts_by_path[path] = scan_pid + + def on_mount_removed(self, vmonitor, mount): + """ + callback run when gio indicates a new volume + has been mounted + """ + + path = mount.get_root().get_path() + + # three scenarios - + # the mount has been scanned but downloading has not yet started + # files are being downloaded from mount (it must be a messy unmount) + # files have finished downloading from mount + + if path in self.mounts_by_path: + scan_pid = self.mounts_by_path[path] + del self.mounts_by_path[path] + # temp directory should be cleaned by finishing of process + + self.thumbnails.clear_all(scan_pid = scan_pid, + keep_downloaded_files = True) + self.device_collection.remove_device(scan_pid) + - if msg: - msg = _("%(freespace)s. %(backuppaths)s.") % {'freespace': msg, 'backuppaths': msg2} - else: - msg = msg2 + + # remove backup volumes + elif path in self.backup_devices: + del self.backup_devices[path] + self.display_free_space() + self.backup_manager.remove_device(path) + self.update_no_backup_devices() + + # may need to disable download button and menu + self.set_download_action_sensitivity() - self.rapid_statusbar.push(self.statusbar_context_id, msg) - - def checkImageDevicePathOnStartup(self): - msg = None - if not os.path.isdir(self.prefs.device_location): - msg = _("Sorry, this device location does not exist:\n%(path)s\n\nPlease resolve the problem, or modify your preferences." % {"path": self.prefs.device_location}) + def clear_non_running_downloads(self): + """ + Clears the display of downloads that are currently not running + """ + + # Stop any processes currently scanning or creating thumbnails + self._terminate_processes(terminate_file_copies=False) + + # Remove them from the user interface + for scan_pid in self.device_collection.get_all_displayed_processes(): + if scan_pid not in self.download_active_by_scan_pid: + self.device_collection.remove_device(scan_pid) + self.thumbnails.clear_all(scan_pid=scan_pid) - if msg: - sys.stderr.write(msg +'\n') - misc.run_dialog(_("Problem with Device Location Folder"), msg, - self, - gtk.MESSAGE_ERROR) - return False - else: - return True - def checkDownloadPathOnStartup(self): - if DOWNLOAD_VIDEO: - paths = ((self.prefs.download_folder, _('Photo')), (self.prefs.video_download_folder, _('Video'))) + + + # # # + # Download and help buttons, and menu items + # # # + + def on_download_action_activate(self, action): + """ + Called when a download is activated + """ + + if self.copy_files_manager.paused: + logger.debug("Download resumed") + self.resume_download() else: - paths = ((self.prefs.download_folder, _('Photo')),) - msg = '' - noProblems = 0 - for path, file_type in paths: - if not os.path.isdir(path): - msg += _("The %(file_type)s Download Folder does not exist.\n") % {'file_type': file_type} - noProblems += 1 - else: - #unfortunately 'os.access(self.prefs.download_folder, os.W_OK)' is not reliable - try: - tempWorkingDir = tempfile.mkdtemp(prefix='rapid-tmp-', - dir=path) - except: - noProblems += 1 - msg += _("The %(file_type)s Download Folder exists but cannot be written to.\n") % {'file_type': file_type} - else: - os.rmdir(tempWorkingDir) + logger.debug("Download activated") - if msg: - msg = _("Sorry, problems were encountered with your download folders. Please fix the problems or modify the preferences.\n\n") + msg - sys.stderr.write(msg) - if noProblems == 1: - title = _("Problem with Download Folder") + if self.download_action_is_download: + if self.need_job_code_for_naming and not self.prompting_for_job_code: + self.get_job_code() + else: + self.start_download() else: - title = _("Problem with Download Folders") - - misc.run_dialog(title, msg, - self, - gtk.MESSAGE_ERROR) - return False - else: - return True + self.pause_download() + - def checkPreferencesOnStartup(self): - prefsOk = rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder, self.prefs.video_rename, self.prefs.video_subfolder) - if not prefsOk: - msg = _("There is an error in the program preferences.") - msg += " " + _("Some preferences will be reset.") - # do not use cmd_line here, as this is a genuine error - sys.stderr.write(msg +'\n') - return prefsOk + def on_help_action_activate(self, action): + webbrowser.open("http://www.damonlynch.net/rapid/documentation") - def needJobCodeForRenaming(self): - return rn.usesJobCode(self.prefs.image_rename) or rn.usesJobCode(self.prefs.subfolder) or rn.usesJobCode(self.prefs.video_rename) or rn.usesJobCode(self.prefs.video_subfolder) + def on_preferences_action_activate(self, action): + + preferencesdialog.PreferencesDialog(self) - def assignJobCode(self, code): - """ assign job code (which may be empty) to global variable and update user preferences + def set_download_action_sensitivity(self): + """ + Sets sensitivity of Download action to enable or disable it + + Affects download button and menu item + """ + if not self.download_is_occurring(): + sensitivity = False + if self.scan_manager.no_tasks == 0: + if self.thumbnails.files_are_checked_to_download(): + sensitivity = True + + self.download_action.set_sensitive(sensitivity) + + def set_download_action_label(self, is_download): + """ + Toggles label betwen pause and download + """ + + if is_download: + self.download_action.set_label(_("Download")) + self.download_action_is_download = True + else: + self.download_action.set_label(_("Pause")) + self.download_action_is_download = False + + # # # + # Job codes + # # # + + + def _init_job_code(self): + self.job_code = self.last_chosen_job_code = '' + self.need_job_code_for_naming = self.prefs.any_pref_uses_job_code() + self.prompting_for_job_code = False + + def assign_job_code(self, code): + """ assign job code (which may be empty) to member variable and update user preferences Update preferences only if code is not empty. Do not duplicate job code. """ - global job_code - if code == None: - code = '' - job_code = code + + self.job_code = code - if job_code: + if code: #add this value to job codes preferences #delete any existing value which is the same #(this way it comes to the front, which is where it should be) @@ -5163,1301 +2001,1272 @@ class RapidApp(gnomeglade.GnomeApp, dbus.service.Object): jcs.remove(code) self.prefs.job_codes = [code] + jcs - - - def getShowWarningDownloadingFromCamera(self): - if self.prefs.show_warning_downloading_from_camera: - cmd_line(_("Displaying warning about downloading directly from camera")) - d = ShowWarningDialog(self.widget, self.gotShowWarningDownloadingFromCamera) - - def gotShowWarningDownloadingFromCamera(self, dialog, showWarningAgain): - dialog.destroy() - self.prefs.show_warning_downloading_from_camera = showWarningAgain - - def getUseDevice(self, path, volume, autostart): - """ Prompt user whether or not to download from this device """ - - cmd_line(_("Prompting whether to use %s" % volume.get_name(limit=0))) - d = UseDeviceDialog(self.widget, path, volume, autostart, self.gotUseDevice) - - def gotUseDevice(self, dialog, userSelected, permanent_choice, path, volume, autostart): - """ User has chosen whether or not to use a device to download from """ - dialog.destroy() - - if userSelected: - if permanent_choice and path not in self.prefs.device_whitelist: - # do not do a list append operation here without the assignment, or the preferences will not be updated! - if len(self.prefs.device_whitelist): - self.prefs.device_whitelist = self.prefs.device_whitelist + [path] - else: - self.prefs.device_whitelist = [path] - self.initiateScan(path, volume, autostart) - - elif permanent_choice and path not in self.prefs.device_blacklist: - # do not do a list append operation here without the assignment, or the preferences will not be updated! - if len(self.prefs.device_blacklist): - self.prefs.device_blacklist = self.prefs.device_blacklist + [path] - else: - self.prefs.device_blacklist = [path] - - def _getJobCode(self, postJobCodeEntryCB, autoStart, downloadSelected): + + def _get_job_code(self, post_job_code_entry_callback): """ prompt for a job code """ if not self.prompting_for_job_code: - cmd_line(_("Prompting for Job Code")) + logger.debug("Prompting for Job Code") self.prompting_for_job_code = True - j = JobCodeDialog(self.widget, self.prefs.job_codes, self.last_chosen_job_code, postJobCodeEntryCB, autoStart, downloadSelected, False) + j = preferencesdialog.JobCodeDialog(parent_window = self.rapidapp, + job_codes = self.prefs.job_codes, + default_job_code = self.last_chosen_job_code, + post_job_code_entry_callback=post_job_code_entry_callback, + entry_only = False) else: - cmd_line(_("Already prompting for Job Code, do not prompt again")) - - def getJobCode(self, autoStart=True, downloadSelected=False): - """ called from the copyphotos thread, or when the user clicks one of the two download buttons""" + logger.debug("Already prompting for Job Code, do not prompt again") - self._getJobCode(self.gotJobCode, autoStart, downloadSelected) + def get_job_code(self): + self._get_job_code(self.got_job_code) - def gotJobCode(self, dialog, userChoseCode, code, autoStart, downloadSelected): + def got_job_code(self, dialog, user_chose_code, code): dialog.destroy() self.prompting_for_job_code = False - if userChoseCode: - self.assignJobCode(code) + if user_chose_code: + if code is None: + code = '' + self.assign_job_code(code) self.last_chosen_job_code = code - self.selection_vbox.selection_treeview.apply_job_code(code, overwrite=False, to_all_rows = not downloadSelected) - threads = self.selection_vbox.selection_treeview.set_status_to_download_pending(selected_only = downloadSelected) - if downloadSelected or not autoStart: - cmd_line(_("Starting downloads")) - self.startDownload(threads) - else: - # autostart is true - cmd_line(_("Starting downloads that have been waiting for a Job Code")) - for w in workers.getWaitingForJobCodeWorkers(): - w.startStop() + logger.debug("Job Code %s entered", self.job_code) + self.start_download() else: # user cancelled - for w in workers.getWaitingForJobCodeWorkers(): - w.waitingForJobCode = False - - if autoStart: - for w in workers.getAutoStartWorkers(): - w.autoStart = False - - def addFile(self, mediaFile): - self.selection_vbox.add_file(mediaFile) - - def update_status_post_download(self, treerowref): - self.selection_vbox.selection_treeview.update_status_post_download(treerowref) - - def on_menu_size_column_toggled(self, widget): - self.prefs.display_size_column = widget.get_active() - self.selection_vbox.selection_treeview.display_size_column(self.prefs.display_size_column) - - def on_menu_type_column_toggled(self, widget): - self.prefs.display_type_column = widget.get_active() - self.selection_vbox.selection_treeview.display_type_column(self.prefs.display_type_column) + logger.debug("No Job Code entered") + self.job_code = '' + self.auto_start_is_on = False + + + # # # + # Download + # # # + + def _init_download_tracking(self): + """ + Initialize variables to track downloads + """ + # Track download sizes and other values for each device. + # (Scan id acts as an index to each device. A device could be scanned + # more than once). + self.download_tracker = downloadtracker.DownloadTracker() - def on_menu_filename_column_toggled(self, widget): - self.prefs.display_filename_column = widget.get_active() - self.selection_vbox.selection_treeview.display_filename_column(self.prefs.display_filename_column) + # Track which temporary directories are created when downloading files + self.temp_dirs_by_scan_pid = dict() - def on_menu_path_column_toggled(self, widget): - self.prefs.display_path_column = widget.get_active() - self.selection_vbox.selection_treeview.display_path_column(self.prefs.display_path_column) + # Track which downloads and backups are running + self.download_active_by_scan_pid = [] + self.backups_active_by_scan_pid = [] - def on_menu_device_column_toggled(self, widget): - self.prefs.display_device_column = widget.get_active() - self.selection_vbox.selection_treeview.display_device_column(self.prefs.display_device_column) - - def checkIfFirstTimeProgramEverRun(self): + + + def start_download(self, scan_pid=None): """ - if this is the first time the program has been run, then - might need to create default directories + Start download, renaming and backup of files. + + If scan_pid is specified, only files matching it will be downloaded """ - if len(self.prefs.program_version) == 0: - path = getDefaultPhotoLocation(ignore_missing_dir=True) - if not os.path.isdir(path): - cmd_line(_("Creating photo download folder %(folder)s") % {'folder':path}) - try: - os.makedirs(path) - self.prefs.download_folder = path - except: - cmd_line(_("Failed to create default photo download folder %(folder)s") % {'folder':path}) - if DOWNLOAD_VIDEO: - path = getDefaultVideoLocation(ignore_missing_dir=True) - if not os.path.isdir(path): - cmd_line(_("Creating video download folder %(folder)s") % {'folder':path}) - try: - os.makedirs(path) - self.prefs.video_download_folder = path - except: - cmd_line(_("Failed to create default video download folder %(folder)s") % {'folder':path}) - - 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. + files_by_scan_pid = self.thumbnails.get_files_checked_for_download(scan_pid) + folders_valid, invalid_dirs = self.check_download_folder_validity(files_by_scan_pid) - returns True if program preferences window should be opened """ + if not folders_valid: + if len(invalid_dirs) > 1: + msg = _("These download folders are invalid:\n%(folder1)s\n%(folder2)s") % { + 'folder1': invalid_dirs[0], 'folder2': invalid_dirs[1]} + else: + msg = _("This download folder is invalid:\n%s") % invalid_dirs[0] + self.log_error(config.CRITICAL_ERROR, _("Download cannot proceed"), + msg) + else: + # set time download is starting if it is not already set + # it is unset when all downloads are completed + if self.download_start_time is None: + self.download_start_time = datetime.datetime.now() + + # Set status to download pending + self.thumbnails.mark_download_pending(files_by_scan_pid) + + # disable refresh and preferences change while download is occurring + self.enable_prefs_and_refresh(enabled=False) + + for scan_pid in files_by_scan_pid: + files = files_by_scan_pid[scan_pid] + # if generating thumbnails for this scan_pid, stop it + if self.thumbnails.terminate_thumbnail_generation(scan_pid): + self.thumbnails.mark_thumbnails_needed(files) + + self.download_files(files, scan_pid) + + self.set_download_action_label(is_download = False) - displayPrefs = upgraded = False + def pause_download(self): - previousVersion = self.prefs.program_version - if len(previousVersion) > 0: - # the program has been run previously for this user + self.copy_files_manager.pause() - pv = common.pythonifyVersion(previousVersion) - rv = common.pythonifyVersion(runningVersion) + # set action to display Download + if not self.download_action_is_download: + self.set_download_action_label(is_download = True) - title = PROGRAM_NAME - imageRename = subfolder = None + self.time_check.pause() - if pv != rv: - if pv > rv: - prefsOk = rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder, self.prefs.video_rename, self.prefs.video_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 rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder, self.prefs.video_rename, self.prefs.video_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 + def resume_download(self): + for scan_pid in self.download_active_by_scan_pid: + self.time_remaining.set_time_mark(scan_pid) + + self.time_check.set_download_mark() + + self.copy_files_manager.start() - do_not_size_icon = False - self.notification_icon_size = 48 - try: - info = pynotify.get_server_info() - except: - cmd_line(_("Warning: desktop environment notification server is incorrectly configured.")) + def download_files(self, files, scan_pid): + """ + Initiate downloading and renaming of files + """ + + # Check which file types will be downloaded for this particular process + if self.files_of_type_present(files, rpdfile.FILE_TYPE_PHOTO): + photo_download_folder = self.prefs.download_folder else: - try: - if info["name"] == 'notify-osd': - do_not_size_icon = True - except: - pass + photo_download_folder = None + + if self.files_of_type_present(files, rpdfile.FILE_TYPE_VIDEO): + video_download_folder = self.prefs.video_download_folder + else: + video_download_folder = None - if do_not_size_icon: - self.application_icon = gtk.gdk.pixbuf_new_from_file( - paths.share_dir('glade3/rapid-photo-downloader.svg')) + download_size = self.size_files_to_be_downloaded(files) + self.download_tracker.init_stats(scan_pid=scan_pid, + bytes=download_size, + no_files=len(files)) + + if self.prefs.backup_images: + download_size = download_size * (len(self.backup_devices) + 1) + + self.time_remaining.set(scan_pid, download_size) + self.time_check.set_download_mark() + + self.download_active_by_scan_pid.append(scan_pid) + + + if len(self.download_active_by_scan_pid) > 1: + self.display_summary_notification = True + + if self.auto_start_is_on and self.prefs.generate_thumbnails: + for rpd_file in files: + rpd_file.generate_thumbnail = True + + # Initiate copy files process + self.copy_files_manager.add_task((photo_download_folder, + video_download_folder, scan_pid, + files)) + + def copy_files_results(self, source, condition): + """ + Handle results from copy files process + """ + #FIXME: must handle early termination / pause of copy files process + connection = self.copy_files_manager.get_pipe(source) + conn_type, msg_data = connection.recv() + if conn_type == rpdmp.CONN_PARTIAL: + msg_type, data = msg_data + + if msg_type == rpdmp.MSG_TEMP_DIRS: + scan_pid, photo_temp_dir, video_temp_dir = data + self.temp_dirs_by_scan_pid[scan_pid] = (photo_temp_dir, video_temp_dir) + elif msg_type == rpdmp.MSG_BYTES: + scan_pid, total_downloaded, chunk_downloaded = data + self.download_tracker.set_total_bytes_copied(scan_pid, + total_downloaded) + self.time_check.increment(bytes_downloaded=chunk_downloaded) + percent_complete = self.download_tracker.get_percent_complete(scan_pid) + self.device_collection.update_progress(scan_pid, percent_complete, + None, None) + self.time_remaining.update(scan_pid, bytes_downloaded=chunk_downloaded) + elif msg_type == rpdmp.MSG_FILE: + download_succeeded, rpd_file, download_count, temp_full_file_name, thumbnail_icon, thumbnail = data + + if thumbnail is not None or thumbnail_icon is not None: + self.thumbnails.update_thumbnail((rpd_file.unique_id, + thumbnail_icon, + thumbnail)) + + self.download_tracker.set_download_count_for_file( + rpd_file.unique_id, download_count) + self.download_tracker.set_download_count( + rpd_file.scan_pid, download_count) + rpd_file.download_start_time = self.download_start_time + + if download_succeeded: + # Insert preference values needed for name generation + rpd_file = prefsrapid.insert_pref_lists(self.prefs, rpd_file) + rpd_file.strip_characters = self.prefs.strip_characters + rpd_file.download_folder = self.prefs.get_download_folder_for_file_type(rpd_file.file_type) + rpd_file.download_conflict_resolution = self.prefs.download_conflict_resolution + rpd_file.synchronize_raw_jpg = self.prefs.must_synchronize_raw_jpg() + rpd_file.job_code = self.job_code + + self.subfolder_file_manager.rename_file_and_move_to_subfolder( + download_succeeded, + download_count, + rpd_file + ) + + return True else: - self.application_icon = gtk.gdk.pixbuf_new_from_file_at_size( - paths.share_dir('glade3/rapid-photo-downloader.svg'), - self.notification_icon_size, self.notification_icon_size) + # Process is complete, i.e. conn_type == rpdmp.CONN_COMPLETE + connection.close() + return False + - - def usingVolumeMonitor(self): + def download_is_occurring(self): + """Returns True if a file is currently being downloaded, renamed or + backed up """ - Returns True if programs needs to use gio or gnomevfs volume monitor - """ - - return (self.prefs.device_autodetection or - (self.prefs.backup_images and - self.prefs.backup_device_autodetection - )) - + return not len(self.download_active_by_scan_pid) == 0 - def startVolumeMonitor(self): - if not self.volumeMonitor: - self.volumeMonitor = VMonitor(self) + # # # + # Create folder and file names for downloaded files + # # # - def displayBackupVolumes(self): + def subfolder_file_results(self, move_succeeded, rpd_file): """ - Create a message to be displayed to the user showing which backup volumes will be used + Handle results of subfolder creation and file renaming """ - 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 + scan_pid = rpd_file.scan_pid + unique_id = rpd_file.unique_id - 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, gMount): - - """ gvfs GProxyShadowMount is used for the camera itself, not the data in the memory card """ - if using_gio: - if hasattr(gMount, 'is_shadowed'): - return gMount.is_shadowed() + if rpd_file.status == config.STATUS_DOWNLOADED_WITH_WARNING: + self.log_error(config.WARNING, rpd_file.error_title, + rpd_file.error_msg, rpd_file.error_extra_detail) + self.error_title = '' + self.error_msg = '' + self.error_extra_detail = '' + + + if self.prefs.backup_images and len(self.backup_devices): + if self.prefs.backup_device_autodetection: + if rpd_file.file_type == rpdfile.FILE_TYPE_PHOTO: + path_suffix = self.prefs.backup_identifier + else: + path_suffix = self.prefs.video_backup_identifier else: - return str(type(gMount)).find('GProxyShadowMount') >= 0 + path_suffix = None + + self.backup_manager.backup_file(move_succeeded, rpd_file, + path_suffix, + self.prefs.backup_duplicate_overwrite) + else: + self.file_download_finished(move_succeeded, rpd_file) + + + def backup_results(self, source, condition): + connection = self.backup_manager.get_pipe(source) + conn_type, msg_data = connection.recv() + if conn_type == rpdmp.CONN_PARTIAL: + msg_type, data = msg_data + + if msg_type == rpdmp.MSG_BYTES: + scan_pid, backup_pid, total_downloaded, chunk_downloaded = data + self.download_tracker.increment_bytes_backed_up(scan_pid, + chunk_downloaded) + self.time_check.increment(bytes_downloaded=chunk_downloaded) + percent_complete = self.download_tracker.get_percent_complete(scan_pid) + self.device_collection.update_progress(scan_pid, percent_complete, + None, None) + self.time_remaining.update(scan_pid, bytes_downloaded=chunk_downloaded) + + elif msg_type == rpdmp.MSG_FILE: + backup_succeeded, rpd_file = data + self.download_tracker.file_backed_up(rpd_file.unique_id) + if self.download_tracker.all_files_backed_up(rpd_file.unique_id): + self.file_download_finished(backup_succeeded, rpd_file) + return True else: return False + + + def file_download_finished(self, succeeded, rpd_file): + scan_pid = rpd_file.scan_pid + unique_id = rpd_file.unique_id + # Update error log window if neccessary + if not succeeded: + self.log_error(config.SERIOUS_ERROR, rpd_file.error_title, + rpd_file.error_msg, rpd_file.error_extra_detail) + + self.thumbnails.update_status_post_download(rpd_file) + self.download_tracker.file_downloaded_increment(scan_pid, + rpd_file.file_type, + rpd_file.status) + + completed, files_remaining = self._update_file_download_device_progress(scan_pid, unique_id) + + if self.download_is_occurring(): + self.update_time_remaining() + + if completed: + # Last file for this scan pid has been downloaded, so clean temp directory + logger.debug("Purging temp directories") + self._clean_temp_dirs_for_scan_pid(scan_pid) + self.download_active_by_scan_pid.remove(scan_pid) + self.time_remaining.remove(scan_pid) + self.notify_downloaded_from_device(scan_pid) + if files_remaining == 0 and self.prefs.auto_unmount: + self.device_collection.unmount(scan_pid) + + + if not self.download_is_occurring(): + logger.debug("Download completed") + self.enable_prefs_and_refresh(enabled=True) + self.notify_download_complete() + self.download_progressbar.set_fraction(0.0) + + self.prefs.stored_sequence_no = self.stored_sequence_value.value + self.downloads_today_tracker.set_raw_downloads_today_from_int(self.downloads_today_value.value) + self.downloads_today_tracker.set_raw_downloads_today_date(self.downloads_today_date_value.value) + self.prefs.set_downloads_today_from_tracker(self.downloads_today_tracker) + + if ((self.prefs.auto_exit and self.download_tracker.no_errors_or_warnings()) + or self.prefs.auto_exit_force): + if not self.thumbnails.files_remain_to_download(): + self._terminate_processes() + gtk.main_quit() + + self.download_tracker.purge_all() + self.speed_label.set_label(" ") + + self.display_free_space() + + self.set_download_action_label(is_download=True) + self.set_download_action_sensitivity() + + self.job_code = '' + self.download_start_time = None + + + def update_time_remaining(self): + update, download_speed = self.time_check.check_for_update() + if update: + self.speed_label.set_text(download_speed) - def isCamera(self, volume): - if using_gio: - try: - return volume.get_root().query_filesystem_info(gio.FILE_ATTRIBUTE_GVFS_BACKEND).get_attribute_as_string(gio.FILE_ATTRIBUTE_GVFS_BACKEND) == 'gphoto2' - except: - return False + time_remaining = self.time_remaining.time_remaining() + if time_remaining: + secs = int(time_remaining) + + 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.pop(self.statusbar_context_id) + self.rapid_statusbar.push(self.statusbar_context_id, message) + + def file_types_by_number(self, no_photos, no_videos): + """ + returns a string to be displayed to the user that can be used + to show if a value refers to photos or videos or both, or just one + of each + """ + if (no_videos > 0) and (no_photos > 0): + v = _('photos and videos') + elif (no_videos == 0) and (no_photos == 0): + v = _('photos or videos') + elif no_videos > 0: + if no_videos > 1: + v = _('videos') + else: + v = _('video') else: - return False + if no_photos > 1: + v = _('photos') + else: + v = _('photo') + return v - def workerHasThisPath(self, path): - havePath= False - for w in workers.getNonFinishedWorkers(): - if w.cardMedia.path == path: - havePath = True - break - return havePath + def notify_downloaded_from_device(self, scan_pid): + device = self.device_collection.get_device(scan_pid) + + if device.mount is None: + notification_name = PROGRAM_NAME + icon = self.application_icon + else: + notification_name = device.get_name() + icon = device.get_icon(self.notification_icon_size) + + no_photos_downloaded = self.download_tracker.get_no_files_downloaded( + scan_pid, rpdfile.FILE_TYPE_PHOTO) + no_videos_downloaded = self.download_tracker.get_no_files_downloaded( + scan_pid, rpdfile.FILE_TYPE_VIDEO) + no_photos_failed = self.download_tracker.get_no_files_failed( + scan_pid, rpdfile.FILE_TYPE_PHOTO) + no_videos_failed = self.download_tracker.get_no_files_failed( + scan_pid, rpdfile.FILE_TYPE_VIDEO) + no_files_downloaded = no_photos_downloaded + no_videos_downloaded + no_files_failed = no_photos_failed + no_videos_failed + no_warnings = self.download_tracker.get_no_warnings(scan_pid) + + file_types = self.file_types_by_number(no_photos_downloaded, no_videos_downloaded) + file_types_failed = self.file_types_by_number(no_photos_failed, no_videos_failed) + message = _("%(noFiles)s %(filetypes)s downloaded") % \ + {'noFiles':no_files_downloaded, 'filetypes': file_types} + + if no_files_failed: + message += "\n" + _("%(noFiles)s %(filetypes)s failed to download") % {'noFiles':no_files_failed, 'filetypes':file_types_failed} + + if no_warnings: + message = "%s\n%s " % (message, no_warnings) + _("warnings") + + n = pynotify.Notification(notification_name, message) + n.set_icon_from_pixbuf(icon) + + n.show() + + def notify_download_complete(self): + if self.display_summary_notification: + message = _("All downloads complete") + + # photo downloads + photo_downloads = self.download_tracker.total_photos_downloaded + if photo_downloads: + filetype = self.file_types_by_number(photo_downloads, 0) + message += "\n" + _("%(number)s %(numberdownloaded)s") % \ + {'number': photo_downloads, + 'numberdownloaded': _("%(filetype)s downloaded") % \ + {'filetype': filetype}} + + # photo failures + photo_failures = self.download_tracker.total_photo_failures + if photo_failures: + filetype = self.file_types_by_number(photo_failures, 0) + message += "\n" + _("%(number)s %(numberdownloaded)s") % \ + {'number': photo_failures, + 'numberdownloaded': _("%(filetype)s failed to download") % \ + {'filetype': filetype}} + + # video downloads + video_downloads = self.download_tracker.total_videos_downloaded + if video_downloads: + filetype = self.file_types_by_number(0, video_downloads) + message += "\n" + _("%(number)s %(numberdownloaded)s") % \ + {'number': video_downloads, + 'numberdownloaded': _("%(filetype)s downloaded") % \ + {'filetype': filetype}} + + # video failures + video_failures = self.download_tracker.total_video_failures + if video_failures: + filetype = self.file_types_by_number(0, video_failures) + message += "\n" + _("%(number)s %(numberdownloaded)s") % \ + {'number': video_failures, + 'numberdownloaded': _("%(filetype)s failed to download") % \ + {'filetype': filetype}} + + # warnings + warnings = self.download_tracker.total_warnings + if warnings: + message += "\n" + _("%(number)s %(numberdownloaded)s") % \ + {'number': warnings, + 'numberdownloaded': _("warnings")} + + n = pynotify.Notification(PROGRAM_NAME, message) + n.set_icon_from_pixbuf(self.application_icon) + n.show() + self.display_summary_notification = False # don't show it again unless needed + - def on_volume_mounted(self, monitor, mount): - """ - callback run when gnomevfs indicates a new volume - has been mounted + def _update_file_download_device_progress(self, scan_pid, unique_id): """ + Increments the progress bar for an individual device - if self.usingVolumeMonitor(): - volume = Volume(mount) - path = volume.get_path() - - if path in self.prefs.device_blacklist and self.searchForPsd(): - cmd_line(_("Device %(device)s (%(path)s) ignored") % { - 'device': volume.get_name(limit=0), 'path': path}) - else: - if not self.isGProxyShadowMount(mount): - self._printDetectedDevice(volume.get_name(limit=0), path) - - isBackupVolume = self.checkIfBackupVolume(path) - - if isBackupVolume: - if path not in self.backupVolumes: - self.backupVolumes[path] = volume - self.displayFreeSpace() - - elif self.prefs.device_autodetection and (media.is_DCIM_Media(path) or self.searchForPsd()): - if self.isCamera(volume.volume): - self.getShowWarningDownloadingFromCamera() - if self.searchForPsd() and path not in self.prefs.device_whitelist: - # prompt user if device should be used or not - self.getUseDevice(path, volume, self.prefs.auto_download_upon_device_insertion) - else: - self._printAutoStart(self.prefs.auto_download_upon_device_insertion) - self.initiateScan(path, volume, self.prefs.auto_download_upon_device_insertion) - - def initiateScan(self, path, volume, autostart): - """ initiates scan of image device""" - cardMedia = CardMedia(path, volume) - i = workers.getNextThread_id() - - workers.append(CopyPhotos(i, self, self.fileRenameLock, - self.fileSequenceLock, self.statsLock, - self.downloadedFilesLock, self.downloadStats, - autostart, cardMedia)) - - - self.setDownloadButtonSensitivity() - self.startScan() - - - def on_volume_unmounted(self, monitor, volume): - """ - callback run when gnomevfs indicates a volume - has been unmounted + Returns if the download is completed for that scan_pid + It also returns the number of files remaining for the scan_pid, BUT + this value is valid ONLY if the download is completed """ - v = Volume(volume) - path = v.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: - if w.cardMedia.volume.volume == volume: - media_collection_treeview.removeCard(w.thread_id) - self.selection_vbox.selection_treeview.clear_all(w.thread_id) - workers.disableWorker(w.thread_id) - # second scenario - for w in workers.getReadyToDownloadWorkers(): - if w.cardMedia.volume: - if w.cardMedia.volume.volume == volume: - media_collection_treeview.removeCard(w.thread_id) - self.selection_vbox.selection_treeview.clear_all(w.thread_id) - workers.disableWorker(w.thread_id) - - # fourth scenario - nothing to do + files_downloaded = self.download_tracker.get_download_count_for_file(unique_id) + files_to_download = self.download_tracker.get_no_files_in_download(scan_pid) + file_types = self.download_tracker.get_file_types_present(scan_pid) + completed = files_downloaded == files_to_download + if completed and self.prefs.backup_images: + completed = self.download_tracker.all_files_backed_up(unique_id) + + if completed: + files_remaining = self.thumbnails.get_no_files_remaining(scan_pid) + else: + files_remaining = 0 - # remove backup volumes - if path in self.backupVolumes: - del self.backupVolumes[path] - self.displayFreeSpace() - - # may need to disable download button - self.setDownloadButtonSensitivity() + if completed and files_remaining: + # e.g.: 3 of 205 photos and videos (202 remaining) + progress_bar_text = _("%(number)s of %(total)s %(filetypes)s (%(remaining)s remaining)") % { + 'number': files_downloaded, + 'total': files_to_download, + 'filetypes': file_types, + 'remaining': files_remaining} + else: + # e.g.: 205 of 205 photos and videos + progress_bar_text = _("%(number)s of %(total)s %(filetypes)s") % \ + {'number': files_downloaded, + 'total': files_to_download, + 'filetypes': file_types} + percent_complete = self.download_tracker.get_percent_complete(scan_pid) + self.device_collection.update_progress(scan_pid=scan_pid, + percent_complete=percent_complete, + progress_bar_text=progress_bar_text, + bytes_downloaded=None) + + percent_complete = self.download_tracker.get_overall_percent_complete() + self.download_progressbar.set_fraction(percent_complete) + + return (completed, files_remaining) - - def clearCompletedDownloads(self): - """ - clears the display of completed downloads - """ - for w in workers.getFinishedWorkers(): - media_collection_treeview.removeCard(w.thread_id) - self.selection_vbox.selection_treeview.clear_all(w.thread_id) - - - - - def clearNotStartedDownloads(self): + def _clean_all_temp_dirs(self): """ - Clears the display of the download and instructs the thread not to run + Cleans all temp dirs if they exist """ - - for w in workers.getNotDownloadingWorkers(): - media_collection_treeview.removeCard(w.thread_id) - workers.disableWorker(w.thread_id) + for scan_pid in self.temp_dirs_by_scan_pid: + for temp_dir in self.temp_dirs_by_scan_pid[scan_pid]: + self._purge_dir(temp_dir) + + self.temp_dirs_by_scan_pid = {} + - def checkIfBackupVolume(self, path): + def _clean_temp_dirs_for_scan_pid(self, scan_pid): """ - Checks to see if backups are enabled and path represents a valid backup location - - Checks against user preferences. + Deletes temp files and folders used in download """ - identifiers = [self.prefs.backup_identifier] - if DOWNLOAD_VIDEO: - identifiers.append(self.prefs.video_backup_identifier) - if self.prefs.backup_images: - if self.prefs.backup_device_autodetection: - if media.isBackupMedia(path, identifiers): - 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): + for temp_dir in self.temp_dirs_by_scan_pid[scan_pid]: + self._purge_dir(temp_dir) + del self.temp_dirs_by_scan_pid[scan_pid] + + def _purge_dir(self, directory): """ - Sets up volumes for downloading from and backing up to + Deletes all files in the directory, and the directory itself. - 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 - being changed - - Removes any image media that are currently not downloaded, - or finished downloading + Does not recursively traverse any subfolders in the directory. """ - self.clearNotStartedDownloads() - - volumeList = [] - self.backupVolumes = {} - - if not workers.noDownloadingWorkers(): - self.downloadStats.clear() - self._resetDownloadInfo() - - if self.usingVolumeMonitor(): - # either using automatically detected backup devices - # or download devices - - for v in self.volumeMonitor.get_mounts(): - volume = Volume(v) #'volumes' are actually mounts (legacy variable name at work here) - path = volume.get_path(avoid_gnomeVFS_bug = True) - - if path: - if path in self.prefs.device_blacklist and self.searchForPsd(): - cmd_line(_("Device %(device)s (%(path)s) ignored") % { - 'device': volume.get_name(limit=0), - 'path': path}) - else: - 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[path] = volume - elif self.prefs.device_autodetection and (media.is_DCIM_Media(path) or self.searchForPsd()): - volumeList.append((path, volume)) - - - if not self.prefs.device_autodetection: - # user manually specified the path from which to download - path = self.prefs.device_location - if path: - cmd_line(_("Using manually specified path") + " %s" % path) - volumeList.append((path, None)) - - if self.prefs.backup_images: - if not self.prefs.backup_device_autodetection: - # user manually specified backup location - # will backup to this path, but don't need any volume info associated with it - self.backupVolumes[self.prefs.backup_location] = None + if directory: + try: + path = gio.File(directory) + # first delete any files in the temp directory + # assume there are no directories in the temp directory + file_attributes = "standard::name,standard::type" + children = path.enumerate_children(file_attributes) + for child in children: + f = path.get_child(child.get_name()) + f.delete(cancellable=None) + path.delete(cancellable=None) + logger.debug("Deleted directory %s", directory) + except gio.Error, inst: + logger.error("Failure deleting temporary folder %s", directory) + logger.error(inst) + + + # # # + # Preferences + # # # - self.displayFreeSpace() - # add each memory card / other device to the list of threads - 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)) + def _init_prefs(self): + self.prefs = prefsrapid.RapidPreferences() + self.prefs.notify_add(self.on_preference_changed) - self._printAutoStart(autoStart) + # flag to indicate whether the user changed some preferences that + # indicate the image and backup devices should be setup again + self.rerun_setup_available_image_and_video_media = False + self.rerun_setup_available_backup_media = False - shownWarning = False + # flag to indicate that the preferences dialog window is being + # displayed to the user + self.preferences_dialog_displayed = False - for i in range(len(volumeList)): - path, volume = volumeList[i] - if volume: - if self.isCamera(volume.volume) and not shownWarning: - self.getShowWarningDownloadingFromCamera() - shownWarning = True - if self.searchForPsd() and path not in self.prefs.device_whitelist: - # prompt user to see if device should be used or not - self.getUseDevice(path, volume, autoStart) - else: - self.initiateScan(path, volume, autoStart) - - def refreshBackupMedia(self): - """ - Setup the backup media + # flag to indicate that the user has modified the download today + # related values in the preferences dialog window + self.refresh_downloads_today = False - Assumptions: this is being called after the user has changed their preferences AND download media has already been setup - """ - self.backupVolumes = {} - if self.prefs.backup_images: - if not self.prefs.backup_device_autodetection: - # user manually specified backup location - # will backup to this path, but don't need any volume info associated with it - self.backupVolumes[self.prefs.backup_location] = None - else: - for v in self.volumeMonitor.get_mounts(): - volume = Volume(v) - path = volume.get_path(avoid_gnomeVFS_bug = True) - if path: - if self.checkIfBackupVolume(path): - # is a backup volume - if path not in self.backupVolumes: - # ensure it is not in a list of workers which have not started downloading - # if it is, remove it - for w in workers.getNotDownloadingAndNotFinishedWorkers(): - if w.cardMedia.path == path: - media_collection_treeview.removeCard(w.thread_id) - self.selection_vbox.selection_treeview.clear_all(w.thread_id) - workers.disableWorker(w.thread_id) - - downloading_workers = [] - for w in workers.getDownloadingWorkers(): - downloading_workers.append(w) - - for w in downloading_workers: - if w.cardMedia.path == path: - # the user is trying to backup to a device that is currently being downloaded from..... we don't normally allow that, but what to do? - cmd_line(_("Warning: backup device %(device)s is currently being downloaded from") % {'device': volume.get_name(limit=0)}) - - self.backupVolumes[path] = volume - - self.displayFreeSpace() + self.downloads_today_tracker = self.prefs.get_downloads_today_tracker() - def _setupDownloadbuttons(self): - self.download_hbutton_box = gtk.HButtonBox() - self.download_hbutton_box.set_spacing(12) - self.download_hbutton_box.set_homogeneous(False) - - help_button = gtk.Button(stock=gtk.STOCK_HELP) - help_button.connect("clicked", self.on_help_button_clicked) - self.download_hbutton_box.pack_start(help_button) - self.download_hbutton_box.set_child_secondary(help_button, True) - - self.DOWNLOAD_SELECTED_LABEL = _("D_ownload Selected") - self.download_button_is_download = True - self.download_button = gtk.Button() - self.download_button.set_use_underline(True) - self.download_button.set_flags(gtk.CAN_DEFAULT) - self.download_selected_button = gtk.Button() - self.download_selected_button.set_use_underline(True) - self._set_download_button() - self.download_button.connect('clicked', self.on_download_button_clicked) - self.download_selected_button.connect('clicked', self.on_download_selected_button_clicked) - self.download_hbutton_box.set_layout(gtk.BUTTONBOX_END) - self.download_hbutton_box.pack_start(self.download_selected_button) - 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_selection(self, value): - if value: - self.selection_vbox.preview_table.show_all() + downloads_today = self.downloads_today_tracker.get_and_maybe_reset_downloads_today() + if downloads_today > 0: + logger.info("Downloads that have occurred so far today: %s", downloads_today) else: - self.selection_vbox.preview_table.hide() - self.selection_vbox.set_display_preview_folders(self.prefs.display_preview_folders) - - def set_display_preview_folders(self, value): - self.selection_vbox.set_display_preview_folders(value) - - def _resetDownloadInfo(self): - self.markSet = False - self.startTime = None - self.totalDownloadSize = self.totalDownloadedSoFar = 0 - self.totalDownloadSizeThisRun = self.totalDownloadedSoFarThisRun = 0 - # there is no need to clear self.timeRemaining, as when each thread is completed, it removes itself - - # this next value is used by the date time option "Download Time" - self.download_start_time = None - - global job_code - job_code = None - - 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 + logger.info("No downloads have occurred so far today") - self.timeMark = self.startTime - self.sizeMark = 0 + self.downloads_today_value = Value(c_int, + self.downloads_today_tracker.get_raw_downloads_today()) + self.downloads_today_date_value = Array(c_char, + self.downloads_today_tracker.get_raw_downloads_today_date()) + self.day_start_value = Array(c_char, + self.downloads_today_tracker.get_raw_day_start()) + self.refresh_downloads_today_value = Value(c_bool, False) + self.stored_sequence_value = Value(c_int, self.prefs.stored_sequence_no) + self.uses_stored_sequence_no_value = Value(c_bool, self.prefs.any_pref_uses_stored_sequence_no()) + self.uses_session_sequece_no_value = Value(c_bool, self.prefs.any_pref_uses_session_sequece_no()) + self.uses_sequence_letter_value = Value(c_bool, self.prefs.any_pref_uses_sequence_letter_value()) - def startOrResumeWorkers(self, threads): - - # resume any paused workers - for w in workers.getPausedDownloadingWorkers(): - w.startStop() - self.timeRemaining.setTimeMark(w) - - # set the time that the download started - this is used - # in the "Download Time" date time renaming option. - self.setDownloadStartTime() - - - #start any new workers that have downloads pending - for i in threads: - workers[i].startStop() + self.prefs.program_version = __version__ - if is_beta and verbose and False: - workers.printWorkerStatus() + def _check_for_sequence_value_use(self): + self.uses_stored_sequence_no_value.value = self.prefs.any_pref_uses_stored_sequence_no() + self.uses_session_sequece_no_value.value = self.prefs.any_pref_uses_session_sequece_no() + self.uses_sequence_letter_value.value = self.prefs.any_pref_uses_sequence_letter_value() - def setDownloadStartTime(self): - if not self.download_start_time: - self.download_start_time = datetime.datetime.now() - - def updateOverallProgress(self, thread_id, bytesDownloaded, percentComplete): + def on_preference_changed(self, key, value): """ - Updates progress bar and status bar text with time remaining - to download images + Called when user changes the program's preferences """ + logger.debug("Preference change detected: %s", key) + + if key == 'show_log_dialog': + self.menu_log_window.set_active(value) + elif key in ['device_autodetection', 'device_autodetection_psd', 'device_location']: + self.rerun_setup_available_image_and_video_media = True + if not self.preferences_dialog_displayed: + self.post_preference_change() - self.totalDownloadedSoFar += bytesDownloaded - self.totalDownloadedSoFarThisRun += bytesDownloaded - - 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")) - job_code = None - if is_beta and verbose and False: - workers.printWorkerStatus() - - else: - now = time.time() - self.timeRemaining.update(thread_id, bytesDownloaded) - - 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) + elif key in ['backup_images', 'backup_device_autodetection', 'backup_location', 'backup_identifier', 'video_backup_identifier']: + self.rerun_setup_available_backup_media = True + if not self.preferences_dialog_displayed: + self.post_preference_change() - timeRemaining = self.timeRemaining.timeRemaining() - if timeRemaining: - secs = int(timeRemaining) + # Downloads today and stored sequence numbers are kept in shared memory, + # so that the subfolderfile daemon process can access and modify them + + # Note, totally ignore any changes in downloads today, as it + # is modified in a special manner via a tracking class - 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.pop(self.statusbar_context_id) - 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) + elif key == 'stored_sequence_no': + if type(value) <> types.IntType: + logger.critical("Stored sequence number value is malformed") + else: + self.stored_sequence_value.value = value + + elif key in ['image_rename', 'subfolder', 'video_rename', 'video_subfolder']: + # Check if stored sequence no is being used + self._check_for_sequence_value_use() + + elif key in ['download_folder', 'video_download_folder']: + self.display_free_space() - def notifyUserAllDownloadsComplete(self): - """ If all downloads are complete, if needed notify the user using libnotify - - Reset progress bar info""" - - if self.downloadComplete(): - if self.displayDownloadSummaryNotification: - message = _("All downloads complete") - if self.downloadStats.noImagesDownloaded: - filetype = file_types_by_number(self.downloadStats.noImagesDownloaded, 0) - message += "\n" + _("%(number)s %(numberdownloaded)s") % \ - {'number': self.downloadStats.noImagesDownloaded, - 'numberdownloaded': _("%(filetype)s downloaded") % \ - {'filetype': filetype}} - if self.downloadStats.noImagesSkipped: - filetype = file_types_by_number(self.downloadStats.noImagesSkipped, 0) - message += "\n" + _("%(number)s %(numberdownloaded)s") % \ - {'number': self.downloadStats.noImagesSkipped, - 'numberdownloaded': _("%(filetype)s failed to download") % \ - {'filetype': filetype}} - if self.downloadStats.noVideosDownloaded: - filetype = file_types_by_number(0, self.downloadStats.noVideosDownloaded) - message += "\n" + _("%(number)s %(numberdownloaded)s") % \ - {'number': self.downloadStats.noVideosDownloaded, - 'numberdownloaded': _("%(filetype)s downloaded") % \ - {'filetype': filetype}} - if self.downloadStats.noVideosSkipped: - filetype = file_types_by_number(0, self.downloadStats.noVideosSkipped) - message += "\n" + _("%(number)s %(numberdownloaded)s") % \ - {'number': self.downloadStats.noVideosSkipped, - 'numberdownloaded': _("%(filetype)s failed to download") % \ - {'filetype': filetype}} - if self.downloadStats.noWarnings: - message += "\n" + _("%(number)s %(numberdownloaded)s") % \ - {'number': self.downloadStats.noWarnings, - 'numberdownloaded': _("warnings")} - if self.downloadStats.noErrors: - message += "\n" + _("%(number)s %(numberdownloaded)s") % \ - {'number': self.downloadStats.noErrors, - 'numberdownloaded': _("errors")} - - n = pynotify.Notification(PROGRAM_NAME, message) - n.set_icon_from_pixbuf(self.application_icon) - n.show() - self.displayDownloadSummaryNotification = False # don't show it again unless needed - # download statistics are cleared in exitOnDownloadComplete() - self._resetDownloadInfo() - self.speed_label.set_text(' ') - self.displayFreeSpace() + def post_preference_change(self): + if self.rerun_setup_available_image_and_video_media: + + logger.info("Download device settings preferences were changed.") + + self.thumbnails.clear_all() + self.setup_devices(on_startup = False, on_preference_change = True, block_auto_start = True) + self._set_device_collection_size() + if self.main_notebook.get_current_page() == 1: # preview of file + self.main_notebook.set_current_page(0) - def exitOnDownloadComplete(self): - if self.downloadComplete(): - if self.prefs.auto_exit: - if not (self.downloadStats.noErrors or self.downloadStats.noWarnings): - self.quit() - # since for whatever reason am not exiting, clear the download statistics - self.downloadStats.clear() - + self.rerun_setup_available_image_and_video_media = False + + if self.rerun_setup_available_backup_media: + if self.using_volume_monitor(): + self.start_volume_monitor() + logger.info("Backup preferences were changed.") + + self.refresh_backup_media() + + self.rerun_setup_available_backup_media = False + + if self.refresh_downloads_today: + self.downloads_today_value.value = self.downloads_today_tracker.get_raw_downloads_today() + self.downloads_today_date_value.value = self.downloads_today_tracker.get_raw_downloads_today_date() + self.day_start_value.value = self.downloads_today_tracker.get_raw_day_start() + self.refresh_downloads_today_value.value = True + self.prefs.set_downloads_today_from_tracker(self.downloads_today_tracker) + + - def downloadFailed(self, thread_id): - if workers.noDownloadingWorkers() == 0: - self.download_button_is_download = True - self._set_download_button() - self.setDownloadButtonSensitivity() + # # # + # Main app window management and setup + # # # - def downloadComplete(self): - return self.totalDownloadedSoFar == self.totalDownloadSize - - def setDownloadButtonSensitivity(self): + def _init_pynotify(self): + """ + Initialize system notification messages + """ + + if not pynotify.init("TestCaps"): + logger.critical("Problem using pynotify.") + gtk.main_quit() - isSensitive = (workers.noReadyToDownloadWorkers() > 0 and - workers.noScanningWorkers() == 0 and - self.selection_vbox.selection_treeview.rows_available_for_download()) or \ - workers.noDownloadingWorkers() > 0 + do_not_size_icon = False + self.notification_icon_size = 48 + try: + info = pynotify.get_server_info() + except: + logger.warning("Desktop environment notification server is incorrectly configured.") + else: + try: + if info["name"] == 'notify-osd': + do_not_size_icon = True + except: + pass - if isSensitive: - self.download_button.props.sensitive = True - # download selected button sensitity is enabled only when the user selects something - self.selection_vbox.selection_treeview.update_download_selected_button() - self.menu_download_pause.props.sensitive = True + if do_not_size_icon: + self.application_icon = gtk.gdk.pixbuf_new_from_file( + paths.share_dir('glade3/rapid-photo-downloader.svg')) else: - self.download_button.props.sensitive = False - self.download_selected_button.props.sensitive = False - self.menu_download_pause.props.sensitive = False - - return isSensitive + self.application_icon = gtk.gdk.pixbuf_new_from_file_at_size( + paths.share_dir('glade3/rapid-photo-downloader.svg'), + self.notification_icon_size, self.notification_icon_size) + + def _init_widgets(self): + """ + Initialize widgets in the main window, and variables that point to them + """ + builder = gtk.Builder() + self.builder = builder + builder.add_from_file(paths.share_dir("glade3/rapid.ui")) + self.rapidapp = builder.get_object("rapidapp") + self.main_vpaned = builder.get_object("main_vpaned") + self.main_notebook = builder.get_object("main_notebook") + self.download_action = builder.get_object("download_action") + self.download_progressbar = builder.get_object("download_progressbar") + self.rapid_statusbar = builder.get_object("rapid_statusbar") + self.statusbar_context_id = self.rapid_statusbar.get_context_id("progress") + self.device_collection_scrolledwindow = builder.get_object("device_collection_scrolledwindow") + self.next_image_action = builder.get_object("next_image_action") + self.prev_image_action = builder.get_object("prev_image_action") + self.menu_log_window = builder.get_object("menu_log_window") + self.speed_label = builder.get_object("speed_label") + self.refresh_action = builder.get_object("refresh_action") + self.preferences_action = builder.get_object("preferences_action") - def on_rapidapp_destroy(self, widget): - """Called when the application is going to quit""" + # Only enable this action when actually displaying a preview + self.next_image_action.set_sensitive(False) + self.prev_image_action.set_sensitive(False) - # save window and component sizes - self.prefs.hpaned_pos = self.selection_vbox.file_hpaned.get_position() - self.prefs.vpaned_pos = self.main_vpaned.get_position() - - x, y = self.rapidapp.get_size() - self.prefs.main_window_size_x = x - self.prefs.main_window_size_y = y - - workers.quitAllWorkers() - - self.flushevents() + # About dialog + builder.add_from_file(paths.share_dir("glade3/about.ui")) + self.about = builder.get_object("about") - display_queue.close("w") - - - def on_rapidapp_window_state_event(self, widget, event): - """ Checkto see if the user maximized the main application window or not. """ - if event.changed_mask & gdk.WINDOW_STATE_MAXIMIZED: - self.prefs.main_window_maximized = event.new_window_state & gdk.WINDOW_STATE_MAXIMIZED - + builder.connect_signals(self) + + self.preview_image = PreviewImage(self, builder) - def on_menu_clear_activate(self, widget): - self.clearCompletedDownloads() - widget.set_sensitive(False) + thumbnails_scrolledwindow = builder.get_object('thumbnails_scrolledwindow') + self.thumbnails = ThumbnailDisplay(self) + thumbnails_scrolledwindow.add(self.thumbnails) - def on_menu_refresh_activate(self, widget): - self.selection_vbox.selection_treeview.clear_all() - self.setupAvailableImageAndBackupMedia(onStartup = False, onPreferenceChange = True, doNotAllowAutoStart = True) + #collection of devices from which to download + self.device_collection_viewport = builder.get_object("device_collection_viewport") + self.device_collection = DeviceCollection(self) + self.device_collection_viewport.add(self.device_collection) - def on_menu_report_problem_activate(self, widget): - webbrowser.open("https://bugs.launchpad.net/rapid") + #error log window + self.error_log = errorlog.ErrorLog(self) + + # monitor to handle mounts and dismounts + self.vmonitor = None + # track scan ids for mount paths - very useful when a device is unmounted + self.mounts_by_path = {} + + # Download action state + self.download_action_is_download = True + + # Track the time a download commences + self.download_start_time = None + + # Whether a system wide notifcation message should be shown + # after a download has occurred in parallel + self.display_summary_notification = False + + # Values used to display how much longer a download will take + self.time_remaining = downloadtracker.TimeRemaining() + self.time_check = downloadtracker.TimeCheck() - 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 _set_window_size(self): + """ + Remember the window size from the last time the program was run, or + set a default size + """ - def on_menu_log_window_toggled(self, widget): - active = widget.get_active() - self.prefs.show_log_dialog = active - if active: - log_dialog.widget.show() + if self.prefs.main_window_maximized: + self.rapidapp.maximize() + self.rapidapp.set_default_size(config.DEFAULT_WINDOW_WIDTH, + config.DEFAULT_WINDOW_HEIGHT) + elif self.prefs.main_window_size_x > 0: + self.rapidapp.set_default_size(self.prefs.main_window_size_x, self.prefs.main_window_size_y) else: - log_dialog.widget.hide() + # set a default size + self.rapidapp.set_default_size(config.DEFAULT_WINDOW_WIDTH, + config.DEFAULT_WINDOW_HEIGHT) + - def on_menu_display_selection_toggled(self, check_button): - self.prefs.display_selection = check_button.get_active() + def _set_device_collection_size(self): + """ + Set the size of the device collection scrolled window widget + """ + if self.device_collection.map_process_to_row: + height = self.device_collection_viewport.size_request()[1] + self.device_collection_scrolledwindow.set_size_request(-1, height) + self.main_vpaned.set_position(height) + else: + # don't allow the media collection to be absolutely empty + self.device_collection_scrolledwindow.set_size_request(-1, 47) - def on_menu_preview_folders_toggled(self, check_button): - self.prefs.display_preview_folders = check_button.get_active() + + def on_rapidapp_window_state_event(self, widget, event): + """ Records the window maximization state in the preferences.""" - def on_menu_zoom_out_activate(self, widget): - self.selection_vbox.zoom_out() + if event.changed_mask & gdk.WINDOW_STATE_MAXIMIZED: + self.prefs.main_window_maximized = event.new_window_state & gdk.WINDOW_STATE_MAXIMIZED - def on_menu_zoom_in_activate(self, widget): - self.selection_vbox.zoom_in() + def _setup_buttons(self): + thumbnails_button = self.builder.get_object("thumbnails_button") + image = gtk.image_new_from_file(paths.share_dir('glade3/thumbnails_icon.png')) + thumbnails_button.set_image(image) - def on_menu_select_all_activate(self, widget): - self.selection_vbox.selection_treeview.select_rows('all') - - def on_menu_select_all_photos_activate(self, widget): - self.selection_vbox.selection_treeview.select_rows('photos') + preview_button = self.builder.get_object("preview_button") + image = gtk.image_new_from_file(paths.share_dir('glade3/photo_icon.png')) + preview_button.set_image(image) + + next_image_button = self.builder.get_object("next_image_button") + image = gtk.image_new_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON) + next_image_button.set_image(image) + + prev_image_button = self.builder.get_object("prev_image_button") + image = gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON) + prev_image_button.set_image(image) + + def _setup_icons(self): + icons = ['rapid-photo-downloader-jobcode',] + icon_list = [(icon, paths.share_dir('glade3/%s.svg' % icon)) for icon in icons] + register_iconsets(icon_list) - def on_menu_select_all_videos_activate(self, widget): - self.selection_vbox.selection_treeview.select_rows('videos') + def _setup_error_icons(self): + """ + hide display of warning and error symbols in the taskbar until they + are needed + """ + self.error_image = self.builder.get_object("error_image") + self.warning_image = self.builder.get_object("warning_image") + self.warning_vseparator = self.builder.get_object("warning_vseparator") + self.error_image.hide() + self.warning_image.hide() + self.warning_vseparator.hide() - def on_menu_select_none_activate(self, widget): - self.selection_vbox.selection_treeview.select_rows('none') + def enable_prefs_and_refresh(self, enabled): + """ + If enable is true, then the user is able to activate the preferences + or refresh command. + The intention is to be able to disable this during a download + """ + self.refresh_action.set_sensitive(enabled) + self.preferences_action.set_sensitive(enabled) + + def statusbar_message(self, msg): + self.rapid_statusbar.push(self.statusbar_context_id, msg) - def on_menu_select_all_with_job_code_activate(self, widget): - self.selection_vbox.selection_treeview.select_rows('withjobcode') - - def on_menu_select_all_without_job_code_activate(self, widget): - self.selection_vbox.selection_treeview.select_rows('withoutjobcode') - + def statusbar_message_remove(self): + self.rapid_statusbar.pop(self.statusbar_context_id) - 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): + def display_backup_mounts(self): """ - Sets download button to appropriate state + Create a message to be displayed to the user showing which backup + mounts will be used """ + message = '' - if self.download_button_is_download: - # This text will be displayed to the user on the Download / Pause button. - self.download_selected_button.set_label(self.DOWNLOAD_SELECTED_LABEL) - self.download_selected_button.set_image(gtk.image_new_from_stock( - gtk.STOCK_CONVERT, - gtk.ICON_SIZE_BUTTON)) - self.selection_vbox.selection_treeview.update_download_selected_button() - - self.download_button.set_image(gtk.image_new_from_stock( - gtk.STOCK_CONVERT, - gtk.ICON_SIZE_BUTTON)) - - if workers.noPausedWorkers(): - self.download_button.set_label(_("_Resume")) - self.download_selected_button.hide() - else: - self.download_button.set_label(_("_Download All")) - self.download_selected_button.show_all() - + paths = self.backup_devices.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.backup_devices[b].get_name()) + + if v > 1: + message = _("Using backup devices") + " %s" % message + elif v == 1: + message = _("Using backup device") + " %s" % message 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")) - self.download_selected_button.set_sensitive(False) - self.download_selected_button.hide() + message = _("No backup devices detected") - def on_menu_download_pause_activate(self, widget): - self.on_download_button_clicked(widget) + return message - 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, threads): - self.startOrResumeWorkers(threads) - 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): + def display_free_space(self): """ - Handle download button click. - - Button is in one of three states: download all, resume, or pause. + Displays the amount of space free on the filesystem the files will be + downloaded to. - If download, a click indicates to start or resume a download run. - If pause, a click indicates to pause all running downloads. + Also displays backup volumes / path being used. """ - if self.download_button_is_download: - if need_job_code_for_renaming and self.selection_vbox.selection_treeview.job_code_missing(False) and not self.prompting_for_job_code: - self.getJobCode(autoStart=False, downloadSelected=False) - else: - threads = self.selection_vbox.selection_treeview.set_status_to_download_pending(selected_only = False) - self.startDownload(threads) - self._set_download_button() + photo_dir = self.is_valid_download_dir(path=self.prefs.download_folder, is_photo_dir=True, show_error_in_log=True) + video_dir = self.is_valid_download_dir(path=self.prefs.video_download_folder, is_photo_dir=False, show_error_in_log=True) + if photo_dir and video_dir: + same_file_system = self.same_file_system(self.prefs.download_folder, + self.prefs.video_download_folder) else: - self.pauseDownload() - - def on_download_selected_button_clicked(self, widget): - # set the status of the selected workers to be downloading pending - if need_job_code_for_renaming and self.selection_vbox.selection_treeview.job_code_missing(True) and not self.prompting_for_job_code: - self.getJobCode(autoStart=False, downloadSelected=True) - else: - threads = self.selection_vbox.selection_treeview.set_status_to_download_pending(selected_only = True) - self.startDownload(threads) + same_file_system = False - + dirs = [] + if photo_dir: + dirs.append((self.prefs.download_folder, _("photos"))) + if video_dir and not same_file_system: + dirs.append((self.prefs.video_download_folder, _("videos"))) + + msg = '' + if len(dirs) > 1: + msg = ' ' + _('Free space:') + ' ' + + for i in range(len(dirs)): + dir_info = dirs[i] + folder = gio.File(dir_info[0]) + file_info = folder.query_filesystem_info(gio.FILE_ATTRIBUTE_FILESYSTEM_FREE) + size = file_info.get_attribute_uint64(gio.FILE_ATTRIBUTE_FILESYSTEM_FREE) + free = format_size_for_user(bytes=size) + if len(dirs) > 1: + #(videos) or (photos) will be appended to the free space message displayed to the + #user in the status bar. + #you should only translate this if your language does not use parantheses + file_type = _("(%(file_type)s)") % {'file_type': dir_info[1]} + + #Freespace available on the filesystem for downloading to + #Displayed in status bar message on main window + msg += _("%(free)s %(file_type)s") % {'free': free, 'file_type': file_type} + if i == 0: + #Inserted in the middle of the statusbar message concerning the amount of freespace + #Used to differentiate between two different file systems + #e.g. Free space: 21.3GB (photos); 14.7GB (videos). + msg += _("; ") + else: + #Inserted at the end of the statusbar message concerning the amount of freespace + #Used to differentiate between two different file systems + #e.g. Free space: 21.3GB (photos); 14.7GB (videos). + msg += _(".") + + else: + #Freespace available on the filesystem for downloading to + #Displayed in status bar message on main window + #e.g. 14.7GB available + msg = " " + _("%(free)s free") % {'free': free} - def on_help_button_clicked(self, widget): - webbrowser.open("http://www.damonlynch.net/rapid/help.html") - def on_preference_changed(self, key, value): + if self.prefs.backup_images: + if not self.prefs.backup_device_autodetection: + # user manually specified backup location + msg2 = _('Backing up to %(path)s') % {'path':self.prefs.backup_location} + else: + msg2 = self.display_backup_mounts() + + if msg: + msg = _("%(freespace)s. %(backuppaths)s.") % {'freespace': msg, 'backuppaths': msg2} + else: + msg = msg2 + + msg = msg.rstrip() + + self.statusbar_message(msg) + + def log_error(self, severity, problem, details, extra_detail=None): """ - Called when user changes the program's preferences + Display error and warning messages to user in log window """ + self.error_log.add_message(severity, problem, details, extra_detail) - if key == 'display_selection': - self.set_display_selection(value) - elif key == 'display_preview_folders': - self.set_display_preview_folders(value) - elif key == 'show_log_dialog': - self.menu_log_window.set_active(value) - elif key in ['device_autodetection', 'device_autodetection_psd', 'device_location']: - self.rerunSetupAvailableImageAndVideoMedia = True - if not self.preferencesDialogDisplayed: - self.postPreferenceChange() - - elif key in ['backup_images', 'backup_device_autodetection', 'backup_location', 'backup_identifier', 'video_backup_identifier']: - self.rerunSetupAvailableBackupMedia = True - if not self.preferencesDialogDisplayed: - self.postPreferenceChange() - - elif key in ['subfolder', 'image_rename', 'video_subfolder', 'video_rename']: - global need_job_code_for_renaming - need_job_code_for_renaming = self.needJobCodeForRenaming() - self.selection_vbox.set_job_code_display() - self.menu_select_all_without_job_code.set_sensitive(need_job_code_for_renaming) - self.menu_select_all_with_job_code.set_sensitive(need_job_code_for_renaming) - self.refreshGeneratedSampleSubfolderAndName = True - - if not self.preferencesDialogDisplayed: - self.postPreferenceChange() - - elif key in ['download_folder', 'video_download_folder']: - self.refreshSampleDownloadFolder = True - if not self.preferencesDialogDisplayed: - self.postPreferenceChange() - - elif key == 'job_codes': - # update job code list in left pane - self.selection_vbox.update_job_code_combo() + + def on_error_eventbox_button_press_event(self, widget, event): + self.prefs.show_log_dialog = True + self.error_log.widget.show() + + def on_menu_log_window_toggled(self, widget): + active = widget.get_active() + self.prefs.show_log_dialog = active + if active: + self.error_log.widget.show() + else: + self.error_log.widget.hide() - def postPreferenceChange(self): + def notify_prefs_are_invalid(self, details): + title = _("Program preferences are invalid") + logger.critical(title) + self.log_error(severity=config.CRITICAL_ERROR, problem=title, + details=details) + + + # # # + # Utility functions + # # # + + def files_of_type_present(self, files, file_type): + """ + Returns true if there is at least one instance of the file_type + in the list of files to be copied + """ + for rpd_file in files: + if rpd_file.file_type == file_type: + return True + return False + + def size_files_to_be_downloaded(self, files): + """ + Returns the total size of the files to be downloaded in bytes """ - Handle changes in program preferences after the preferences dialog window has been closed + size = 0 + for i in range(len(files)): + size += files[i].size + + return size + + def check_download_folder_validity(self, files_by_scan_pid): """ - if self.rerunSetupAvailableImageAndVideoMedia: - if self.usingVolumeMonitor(): - self.startVolumeMonitor() - cmd_line("\n" + _("Download device settings preferences were changed.")) + Checks validity of download folders based on the file types the user + is attempting to download. + + If valid, returns a tuple of True and an empty list. + If invalid, returns a tuple of False and a list of the invalid directores. + """ + valid = True + invalid_dirs = [] + # first, check what needs to be downloaded - photos and / or videos + need_photo_folder = False + need_video_folder = False + while not need_photo_folder and not need_video_folder: + for scan_pid in files_by_scan_pid: + files = files_by_scan_pid[scan_pid] + if not need_photo_folder: + if self.files_of_type_present(files, rpdfile.FILE_TYPE_PHOTO): + need_photo_folder = True + if not need_video_folder: + if self.files_of_type_present(files, rpdfile.FILE_TYPE_VIDEO): + need_video_folder = True - self.selection_vbox.selection_treeview.clear_all() - self.setupAvailableImageAndBackupMedia(onStartup = False, onPreferenceChange = True, doNotAllowAutoStart = True) - if is_beta and verbose and False: - workers.printWorkerStatus() + # second, check validity + if need_photo_folder: + if not self.is_valid_download_dir(self.prefs.download_folder, + is_photo_dir=True): + valid = False + invalid_dirs.append(self.prefs.download_folder) - self.rerunSetupAvailableImageAndVideoMedia = False - - if self.rerunSetupAvailableBackupMedia: - if self.usingVolumeMonitor(): - self.startVolumeMonitor() - cmd_line("\n" + _("Backup preferences were changed.")) - - self.refreshBackupMedia() - self.rerunSetupAvailableBackupMedia = False - - if self.refreshGeneratedSampleSubfolderAndName: - cmd_line("\n" + _("Subfolder and filename preferences were changed.")) - for w in workers.getScanningWorkers(): - if not w.scanResultsStale: - w.scanResultsStale = True - self.noAfterScanRefreshGeneratedSampleSubfolderAndName += 1 + if need_video_folder: + if not self.is_valid_download_dir(self.prefs.video_download_folder, + is_photo_dir=False): + valid = False + invalid_dirs.append(self.prefs.video_download_folder) - self.selection_vbox.selection_treeview.refreshGeneratedSampleSubfolderAndName() - self.refreshGeneratedSampleSubfolderAndName = False - self.setDownloadButtonSensitivity() - - if self.refreshSampleDownloadFolder: - cmd_line("\n" + _("Download folder preferences were changed.")) - for w in workers.getScanningWorkers(): - if not w.scanResultsStaleDownloadFolder: - w.scanResultsStaleDownloadFolder = True - self.noAfterScanRefreshSampleDownloadFolders += 1 - - self.selection_vbox.selection_treeview.refreshSampleDownloadFolders() - self.refreshSampleDownloadFolder = False + return (valid, invalid_dirs) - def regenerateScannedDevices(self, thread_id): + def same_file_system(self, file1, file2): + """Returns True if the files / diretories are on the same file system """ - Regenerate the filenames / subfolders / download folders for this thread + f1 = gio.File(file1) + f2 = gio.File(file2) + f1_info = f1.query_info(gio.FILE_ATTRIBUTE_ID_FILESYSTEM) + f1_id = f1_info.get_attribute_string(gio.FILE_ATTRIBUTE_ID_FILESYSTEM) + f2_info = f2.query_info(gio.FILE_ATTRIBUTE_ID_FILESYSTEM) + f2_id = f2_info.get_attribute_string(gio.FILE_ATTRIBUTE_ID_FILESYSTEM) + return f1_id == f2_id - The user must have adjusted their preferences as the device was being scanned + + def same_file(self, file1, file2): + """Returns True if the files / directories are the same """ + f1 = gio.File(file1) + f2 = gio.File(file2) - if self.noAfterScanRefreshSampleDownloadFolders: - # no point updating it if we're going to update it in the - # refresh of sample names and subfolders anway! - if not self.noAfterScanRefreshGeneratedSampleSubfolderAndName: - self.selection_vbox.selection_treeview.refreshSampleDownloadFolders(thread_id) - self.noAfterScanRefreshSampleDownloadFolders -= 1 - - if self.noAfterScanRefreshGeneratedSampleSubfolderAndName: - self.selection_vbox.selection_treeview.refreshGeneratedSampleSubfolderAndName(thread_id) - self.noAfterScanRefreshGeneratedSampleSubfolderAndName -= 1 - - + file_attributes = "id::file" + f1_info = f1.query_filesystem_info(file_attributes) + f1_id = f1_info.get_attribute_string(gio.FILE_ATTRIBUTE_ID_FILE) + f2_info = f2.query_filesystem_info(file_attributes) + f2_id = f2_info.get_attribute_string(gio.FILE_ATTRIBUTE_ID_FILE) + return f1_id == f2_id - - 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) + def is_valid_download_dir(self, path, is_photo_dir, show_error_in_log=False): + """ + Checks the following conditions: + Does the directory exist? + Is it writable? + + if show_error_in_log is True, then display warning in log window, using + is_photo_dir, which if true means the download directory is for photos, + if false, for Videos + """ + valid = False + if is_photo_dir: + download_folder_type = _("Photo") 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) + download_folder_type = _("Video") + try: + d = gio.File(path) + if not d.query_exists(cancellable=None): + logger.error("%s download folder does not exist: %s", + download_folder_type, path) + if show_error_in_log: + severity = config.WARNING + problem = _("%(file_type)s download folder does not exist") % { + 'file_type': download_folder_type} + details = _("Folder: %s") % path + self.log_error(severity, problem, details) + else: + file_attributes = "standard::type,access::can-read,access::can-write" + file_info = d.query_filesystem_info(file_attributes) + file_type = file_info.get_file_type() + + if file_type != gio.FILE_TYPE_DIRECTORY and file_type != gio.FILE_TYPE_UNKNOWN: + logger.error("%s download folder is invalid: %s", + download_folder_type, path) + if show_error_in_log: + severity = config.WARNING + problem = _("%(file_type)s download folder is invalid") % { + 'file_type': download_folder_type} + details = _("Folder: %s") % path + self.log_error(severity, problem, details) + else: + # is the directory writable? + try: + temp_dir = tempfile.mkdtemp(prefix="rpd-tmp", dir=path) + valid = True + except: + logger.error("%s is not writable", path) + if show_error_in_log: + severity = config.WARNING + problem = _("%(file_type)s download folder is not writable") % { + 'file_type': download_folder_type} + details = _("Folder: %s") % path + self.log_error(severity, problem, details) + else: + f = gio.File(temp_dir) + f.delete(cancellable=None) - def get_mounts(self): - if using_gio: - return self.vmonitor.get_mounts() - else: - return self.vmonitor.get_mounted_volumes() + except gio.Error, inst: + logger.error("Error checking download directory %s", path) + logger.error(inst) -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 + return valid + + + + # # # + # Process results and management + # # # - 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 _start_process_managers(self): + """ + Set up process managers. - def get_icon_pixbuf(self, size): - """ returns icon for the volume, or None if not available""" + A task such as scanning a device or copying files is handled in its + own process. + """ - return common.get_icon_pixbuf(using_gio, self.volume.get_icon(), size) - - def unmount(self, callback): - self.volume.unmount(callback) - -class DownloadStats: - def __init__(self): - self.clear() + self.batch_size = 10 + self.batch_size_MB = 2 - def adjust(self, size, noImagesDownloaded, noVideosDownloaded, noImagesSkipped, noVideosSkipped, noWarnings, noErrors): - self.downloadSize += size - self.noImagesDownloaded += noImagesDownloaded - self.noVideosDownloaded += noVideosDownloaded - self.noImagesSkipped += noImagesSkipped - self.noVideosSkipped += noVideosSkipped - self.noWarnings += noWarnings - self.noErrors += noErrors - - def clear(self): - self.noImagesDownloaded = self.noVideosDownloaded = self.noImagesSkipped = self.noVideosSkipped = 0 - self.downloadSize = 0 - self.noWarnings = self.noErrors = 0 - -class DownloadedFiles: - def __init__(self): - self.images = {} - - def add_download(self, name, extension, date_time, sub_seconds, sequence_number_used): - if name not in self.images: - self.images[name] = ([extension], date_time, sub_seconds, sequence_number_used) - else: - if extension not in self.images[name][0]: - self.images[name][0].append(extension) - + sequence_values = (self.downloads_today_value, + self.downloads_today_date_value, + self.day_start_value, + self.refresh_downloads_today_value, + self.stored_sequence_value, + self.uses_stored_sequence_no_value, + self.uses_session_sequece_no_value, + self.uses_sequence_letter_value) + + self.subfolder_file_manager = SubfolderFileManager( + self.subfolder_file_results, + sequence_values) + - def matching_pair(self, name, extension, date_time, sub_seconds): - """Checks to see if the image matches an image that has already been downloaded. - Image name (minus extension), exif date time, and exif subseconds are checked. + self.generate_folder = False + self.scan_manager = ScanManager(self.scan_results, self.batch_size, + self.generate_folder, self.device_collection.add_device) + self.copy_files_manager = CopyFilesManager(self.copy_files_results, + self.batch_size_MB) + self.backup_manager = BackupFilesManager(self.backup_results, + self.batch_size_MB) - Returns -1 and a sequence number if the name, extension, and exif values match (i.e. it has already been downloaded) - Returns 0 and a sequence number if name and exif values match, but the extension is different (i.e. a matching RAW + JPG image) - Returns -99 and a sequence number of None if images detected with the same filenames, but taken at different times - Returns 1 and a sequence number of None if no match""" - if name in self.images: - if self.images[name][1] == date_time and self.images[name][2] == sub_seconds: - if extension in self.images[name][0]: - return (-1, self.images[name][3]) - else: - return (0, self.images[name][3]) - else: - return (-99, None) - return (1, None) + def scan_results(self, source, condition): + """ + Receive results from scan processes + """ + connection = self.scan_manager.get_pipe(source) - def extExifDateTime(self, name): - """Returns first extension, exif date time and subseconds data for the already downloaded image""" - return (self.images[name][0][0], self.images[name][1], self.images[name][2]) + conn_type, data = connection.recv() -class TimeForDownload: - # used to store variables, see below - pass + if conn_type == rpdmp.CONN_COMPLETE: + connection.close() + self.scan_manager.no_tasks -= 1 + size, file_type_counter, scan_pid = data + size = format_size_for_user(bytes=size) + results_summary, file_types_present = file_type_counter.summarize_file_count() + self.download_tracker.set_file_types_present(scan_pid, file_types_present) + logger.info('Found %s' % results_summary) + logger.info('Files total %s' % size) + self.device_collection.update_device(scan_pid, size) + self.device_collection.update_progress(scan_pid, 0.0, results_summary, 0) + self.set_download_action_sensitivity() + + if (not self.auto_start_is_on and + self.prefs.generate_thumbnails): + self.download_progressbar.set_text(_("Thumbnails")) + self.thumbnails.generate_thumbnails(scan_pid) + elif self.auto_start_is_on: + if self.need_job_code_for_naming and not self.job_code: + self.get_job_code() + else: + self.start_download(scan_pid=scan_pid) -class TimeRemaining: - gap = 2 - def __init__(self): - self.clear() - - def set(self, w, size): - 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 / float(amtTime) - amtToDownload = float(self.times[w].size) - self.times[w].downloaded - if timefraction: - self.times[w].timeRemaining = amtToDownload / timefraction - - def _timeEstimates(self): - for t in self.times: - yield self.times[t].timeRemaining + self.set_thumbnail_sort() - def timeRemaining(self): - return max(self._timeEstimates()) - - def setTimeMark(self, w): - if w in self.times: - self.times[w].timeMark = time.time() + # signal that no more data is coming, finishing io watch for this pipe + return False + else: + if len(data) > self.batch_size: + logger.critical("incoming pipe length is unexpectedly long: %s" % len(data)) + else: + for rpd_file in data: + self.thumbnails.add_file(rpd_file=rpd_file, + generate_thumbnail = not self.auto_start_is_on) - def clear(self): - self.times = {} + # must return True for this method to be called again + return True - def remove(self, w): - if w in self.times: - del self.times[w] -def programStatus(): - print _("Goodbye") + @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 + gtk.main() -def start (): - global is_beta - is_beta = config.version.find('~b') > 0 +def start(): + + is_beta = config.version.find('~') > 0 - parser = OptionParser(version= "%%prog %s" % config.version) + parser = OptionParser(version= "%%prog %s" % utilities.human_readable_version(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. @@ -6468,19 +3277,18 @@ def start (): parser.add_option("-e", "--extensions", action="store_true", dest="extensions", help=_("list photo and video file extensions the program recognizes and exit")) parser.add_option("--reset-settings", action="store_true", dest="reset", help=_("reset all program settings and preferences and exit")) (options, args) = parser.parse_args() - global verbose - verbose = options.verbose - global debug_info - debug_info = options.debug - if debug_info: - verbose = True + if options.debug: + logging_level = logging.DEBUG + elif options.verbose: + logging_level = logging.INFO + else: + logging_level = logging.ERROR - if verbose: - atexit.register(programStatus) - + logger.setLevel(logging_level) + if options.extensions: - extensions = ((metadata.RAW_FILE_EXTENSIONS + metadata.NON_RAW_IMAGE_FILE_EXTENSIONS, _("Photos:")), (videometadata.VIDEO_FILE_EXTENSIONS, _("Videos:"))) + extensions = ((rpdfile.RAW_FILE_EXTENSIONS + rpdfile.NON_RAW_IMAGE_FILE_EXTENSIONS, _("Photos:")), (rpdfile.VIDEO_FILE_EXTENSIONS, _("Videos:"))) for exts, file_type in extensions: v = '' for e in exts[:-1]: @@ -6496,43 +3304,25 @@ def start (): print _("All settings and preferences have been reset") sys.exit(0) - cmd_line(_("Rapid Photo Downloader") + " %s" % config.version) - cmd_line(_("Using") + " pyexiv2 " + metadata.version_info()) - cmd_line(_("Using") + " exiv2 " + metadata.exiv2_version_info()) + logger.info("Rapid Photo Downloader %s", utilities.human_readable_version(config.version)) + logger.info("Using pyexiv2 %s", metadataphoto.pyexiv2_version_info()) + logger.info("Using exiv2 %s", metadataphoto.exiv2_version_info()) if DOWNLOAD_VIDEO: - cmd_line(_("Using") + " hachoir " + videometadata.version_info()) + logger.info("Using hachoir %s", metadatavideo.version_info()) else: - cmd_line(_("\n" + "Video downloading functionality disabled.\nTo download videos, please install the hachoir metadata and kaa metadata packages for python.") + "\n") - - if using_gio: - cmd_line(_("Using") + " GIO") - gobject.threads_init() - else: - # Which volume management code is being used (GIO or GnomeVFS) - cmd_line(_("Using") + " GnomeVFS") - gdk.threads_init() - - + logger.info(_("Video downloading functionality disabled.\nTo download videos, please install the hachoir metadata and kaa metadata packages for python.")) - 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) + 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 + print "Rapid Photo Downloader is already running" object = bus.get_object (config.DBUS_NAME, "/") app = dbus.Interface (object, config.DBUS_NAME) - app.start() - - gdk.threads_leave() + app.start() if __name__ == "__main__": start() diff --git a/rapid/renamesubfolderprefs.py b/rapid/renamesubfolderprefs.py deleted file mode 100644 index d538030..0000000 --- a/rapid/renamesubfolderprefs.py +++ /dev/null @@ -1,1695 +0,0 @@ -#!/usr/bin/python -# -*- coding: latin1 -*- - -### Copyright (C) 2007, 2008, 2009, 2010 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 config - -from common import pythonifyVersion -import problemnotification as pn - - -# 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 you MUST change the value in class i18TranslateMeThanks as well!! - -# *** Level 0 -DATE_TIME = 'Date time' -TEXT = 'Text' -FILENAME = 'Filename' -METADATA = 'Metadata' -SEQUENCES = 'Sequences' -JOB_CODE = 'Job code' - -SEPARATOR = os.sep - -# *** Level 1 - -# Date time -IMAGE_DATE = 'Image date' -TODAY = 'Today' -YESTERDAY = 'Yesterday' -VIDEO_DATE = 'Video date' -DOWNLOAD_TIME = 'Download time' - -# File name -NAME_EXTENSION = 'Name + extension' -NAME = 'Name' -EXTENSION = 'Extension' -IMAGE_NUMBER = 'Image number' -VIDEO_NUMBER = 'Video 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' - -# Video metadata -CODEC = 'Codec' -WIDTH = 'Width' -HEIGHT = 'Height' -FPS = 'Frames Per Second' -LENGTH = 'Length' - -#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" -SEQUENCE_NUMBER_7 = "Seven digits" - - -# Now, define dictionaries and lists of valid combinations of preferences. - -# Level 2 - -# Date - -SUBSECONDS = 'Subseconds' - -# ****** NOTE 1: if changing LIST_DATE_TIME_L2, you MUST update the default subfolder preference below ***** -# ****** NOTE 2: if changing LIST_DATE_TIME_L2, you MUST update DATE_TIME_CONVERT below ***** -LIST_DATE_TIME_L2 = ['YYYYMMDD', 'YYYY-MM-DD','YYMMDD', 'YY-MM-DD', - 'MMDDYYYY', 'MMDDYY', 'MMDD', - 'DDMMYYYY', 'DDMMYY', 'YYYY', 'YY', - 'MM', 'DD', - 'HHMMSS', 'HHMM', 'HH-MM-SS', 'HH-MM', 'HH', 'MM (minutes)', 'SS'] - - -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]] -DEFAULT_VIDEO_SUBFOLDER_PREFS = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[9], '/', '', '', DATE_TIME, VIDEO_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') - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#jobcode - _('Job code') - _('Image date') - _('Video date') - _('Today') - _('Yesterday') - # Translators: Download time is the time and date that the download started (when the user clicked the Download button) - _('Download time') - # 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') - _('Video 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') - _('Codec') - _('Width') - _('Height') - _('Length') - _('Frames Per Second') - # 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") - _("Seven 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') - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime - _('HH-MM-SS') - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime - _('HH-MM') - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime - _('HH') - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime - _('MM (minutes)') - # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime - _('SS') - - -# 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', '%H-%M-%S', '%H-%M', - '%H', '%M', '%S'] - - -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, - SEQUENCE_NUMBER_7, - ] - - - -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, DOWNLOAD_TIME] -LIST_VIDEO_DATE_TIME_L1 = [VIDEO_DATE, TODAY, YESTERDAY, DOWNLOAD_TIME] - -DICT_DATE_TIME_L1 = { - IMAGE_DATE: LIST_IMAGE_DATE_TIME_L2, - TODAY: LIST_DATE_TIME_L2, - YESTERDAY: LIST_DATE_TIME_L2, - DOWNLOAD_TIME: LIST_DATE_TIME_L2, - ORDER_KEY: LIST_DATE_TIME_L1 - } - -VIDEO_DICT_DATE_TIME_L1 = { - VIDEO_DATE: LIST_IMAGE_DATE_TIME_L2, - TODAY: LIST_DATE_TIME_L2, - YESTERDAY: LIST_DATE_TIME_L2, - DOWNLOAD_TIME: LIST_DATE_TIME_L2, - ORDER_KEY: LIST_VIDEO_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_VIDEO_FILENAME_L1 = [NAME_EXTENSION, NAME, EXTENSION, VIDEO_NUMBER] - -DICT_VIDEO_FILENAME_L1 = { - NAME_EXTENSION: LIST_CASE_L2, - NAME: LIST_CASE_L2, - EXTENSION: LIST_CASE_L2, - VIDEO_NUMBER: LIST_IMAGE_NUMBER_L2, - ORDER_KEY: LIST_VIDEO_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] - -LIST_VIDEO_METADATA_L1 = [CODEC, WIDTH, HEIGHT, LENGTH, FPS] - -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 - } - -DICT_VIDEO_METADATA_L1 = { - CODEC: LIST_CASE_L2, - WIDTH: None, - HEIGHT: None, - LENGTH: None, - FPS: None, - ORDER_KEY: LIST_VIDEO_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, JOB_CODE] - -LIST_VIDEO_RENAME_L0 = LIST_IMAGE_RENAME_L0 - - -DICT_IMAGE_RENAME_L0 = { - DATE_TIME: DICT_DATE_TIME_L1, - TEXT: None, - FILENAME: DICT_FILENAME_L1, - METADATA: DICT_METADATA_L1, - SEQUENCES: DICT_SEQUENCE_L1, - JOB_CODE: None, - ORDER_KEY: LIST_IMAGE_RENAME_L0 - } - -DICT_VIDEO_RENAME_L0 = { - DATE_TIME: VIDEO_DICT_DATE_TIME_L1, - TEXT: None, - FILENAME: DICT_VIDEO_FILENAME_L1, - METADATA: DICT_VIDEO_METADATA_L1, - SEQUENCES: DICT_SEQUENCE_L1, - JOB_CODE: None, - ORDER_KEY: LIST_VIDEO_RENAME_L0 - } - -LIST_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, JOB_CODE, SEPARATOR] - -DICT_SUBFOLDER_L0 = { - DATE_TIME: DICT_DATE_TIME_L1, - TEXT: None, - FILENAME: DICT_SUBFOLDER_FILENAME_L1, - METADATA: DICT_METADATA_L1, - JOB_CODE: None, - SEPARATOR: None, - ORDER_KEY: LIST_SUBFOLDER_L0 - } - -LIST_VIDEO_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, JOB_CODE, SEPARATOR] - -DICT_VIDEO_SUBFOLDER_L0 = { - DATE_TIME: VIDEO_DICT_DATE_TIME_L1, - TEXT: None, - FILENAME: DICT_SUBFOLDER_FILENAME_L1, - METADATA: DICT_VIDEO_METADATA_L1, - JOB_CODE: None, - SEPARATOR: None, - ORDER_KEY: LIST_VIDEO_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 usesJobCode(prefs): - """ Returns True if the preferences contain a job code, else returns False""" - for i in range(0, len(prefs), 3): - if prefs[i] == JOB_CODE: - return True - return False - -def checkPreferencesForValidity(imageRenamePrefs, subfolderPrefs, videoRenamePrefs, videoSubfolderPrefs, version=config.version): - """ - Checks preferences for validity (called at program startup) - - Returns true if the passed in preferences are valid, else returns False - """ - - if version == config.version: - try: - tests = ((imageRenamePrefs, ImageRenamePreferences), - (subfolderPrefs, SubfolderPreferences), - (videoRenamePrefs, VideoRenamePreferences), - (videoSubfolderPrefs, VideoSubfolderPreferences)) - for i, Prefs in tests: - p = Prefs(i, None) - p.checkPrefsForValidity() - 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) - checkPreferenceValid(DICT_VIDEO_SUBFOLDER_L0, videoSubfolderPrefs) - checkPreferenceValid(DICT_VIDEO_RENAME_L0, videoRenamePrefs) - 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): - """ - Make the preferences presentable to the user - """ - - 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:") + "\n %s" % self.unpackList(error) - -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) - # must name the combo box on pygtk used in Ubuntu 11.04, Fedora 15, etc. - self.set_name('GtkComboBox') - - 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 - - self.job_code = '' - - # 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 - self.L1DateCheck = IMAGE_DATE #used in _getDateComponent() - self.component = pn.FILENAME_COMPONENT - - - def initializeProblem(self, problem): - """ - Set the problem tracker used in name generation - """ - self.problem = problem - - def getProblems(self): - """ - Returns Problem class if there were problems, else returns None. - """ - if self.problem.has_problem(): - return self.problem - else: - return None - - 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): - if (self.prefList[i+1] or self.prefList[i+2]): - c = ':' - else: - c = '' - s = "%s%s " % (self.prefList[i], c) - - 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 setJobCode(self, job_code): - self.job_code = job_code - - def setDownloadStartTime(self, download_start_time): - self.download_start_time = download_start_time - - def _getDateComponent(self): - """ - Returns portion of new image / subfolder name based on date time. - If the date is missing, will attempt to use the fallback date. - """ - - # step 1: get the correct value from metadata - if self.L1 == self.L1DateCheck: - if self.L2 == SUBSECONDS: - d = self.metadata.subSeconds() - if d == '00': - self.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L2)) - return '' - else: - return d - else: - d = self.metadata.dateTime(missing=None) - - elif self.L1 == TODAY: - d = datetime.datetime.now() - elif self.L1 == YESTERDAY: - delta = datetime.timedelta(days = 1) - d = datetime.datetime.now() - delta - elif self.L1 == DOWNLOAD_TIME: - d = self.download_start_time - else: - raise("Date options invalid") - - # step 2: handle a missing value - if not d: - if self.fallback_date: - try: - d = datetime.datetime.fromtimestamp(self.fallback_date) - except: - self.problem.add_problem(self.component, pn.INVALID_DATE_TIME, '') - return '' - else: - self.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L1)) - return '' - - try: - return d.strftime(convertDateForStrftime(self.L2)) - except: - self.problem.add_problem(self.component, pn.INVALID_DATE_TIME, d) - return '' - - def _getFilenameComponent(self): - """ - Returns portion of new image / subfolder name based on the file name - """ - - name, extension = os.path.splitext(self.existingFilename) - - 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: - self.problem.add_problem(self.component, pn.MISSING_FILE_EXTENSION) - return "" - elif self.L1 == IMAGE_NUMBER or self.L1 == VIDEO_NUMBER: - n = re.search("(?P<image_number>[0-9]+$)", name) - if not n: - self.problem.add_problem(self.component, pn.MISSING_IMAGE_NUMBER) - return '' - 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 - - def _getMetadataComponent(self): - """ - Returns portion of new image / subfolder name based on the metadata - - Note: date time metadata found in _getDateComponent() - """ - - if self.L1 == APERTURE: - v = self.metadata.aperture() - elif self.L1 == ISO: - v = self.metadata.iso() - elif self.L1 == EXPOSURE_TIME: - v = self.metadata.exposureTime(alternativeFormat=True) - elif self.L1 == FOCAL_LENGTH: - v = self.metadata.focalLength() - elif self.L1 == CAMERA_MAKE: - v = self.metadata.cameraMake() - elif self.L1 == CAMERA_MODEL: - v = self.metadata.cameraModel() - elif self.L1 == SHORT_CAMERA_MODEL: - v = self.metadata.shortCameraModel() - elif self.L1 == SHORT_CAMERA_MODEL_HYPHEN: - v = self.metadata.shortCameraModel(includeCharacters = "\-") - elif self.L1 == SERIAL_NUMBER: - v = self.metadata.cameraSerial() - elif self.L1 == SHUTTER_COUNT: - v = self.metadata.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.metadata.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: - self.problem.add_problem(self.component, pn.MISSING_METADATA, _(self.L1)) - return v - - - 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 - """ - - 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 - - def _getSessionSequenceNo(self): - return self._formatSequenceNo(self.sequences.getSessionSequenceNoUsingCounter(self.sequenceCounter), self.L2) - - def _getDownloadsTodaySequenceNo(self): - return self._formatSequenceNo(self.sequences.getDownloadsTodayUsingCounter(self.sequenceCounter), self.L2) - - - def _getStoredSequenceNo(self): - return self._formatSequenceNo(self.sequences.getStoredSequenceNoUsingCounter(self.sequenceCounter), self.L2) - - def _getSequenceLetter(self): - return self._calculateLetterSequence(self.sequences.getSequenceLetterUsingCounter(self.sequenceCounter)) - - - def _getSequencesComponent(self): - 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 - elif self.L0 == FILENAME: - return self._getFilenameComponent() - elif self.L0 == METADATA: - return self._getMetadataComponent() - elif self.L0 == SEQUENCES: - return self._getSequencesComponent() - elif self.L0 == JOB_CODE: - return self.job_code - elif self.L0 == SEPARATOR: - return os.sep - except: - self.problem.add_problem(self.component, pn.ERROR_IN_GENERATION, _(self.L0)) - return '' - - 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, metadata, existingFilename, stripCharacters, subfolder, stripInitialPeriodFromExtension, sequence, fallback_date): - self.metadata = metadata - self.existingFilename = existingFilename - self.stripInitialPeriodFromExtension = stripInitialPeriodFromExtension - self.fallback_date = fallback_date - - name = '' - - #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 = self._getComponent() - if v: - name += v - - if stripCharacters: - for c in r'\:*?"<>|': - name = name.replace(c, '') - - if self.stripForwardSlash: - name = name.replace('/', '') - - name = name.strip() - - return name - - def generateNameUsingPreferences(self, metadata, existingFilename=None, - stripCharacters = False, subfolder=None, - stripInitialPeriodFromExtension=False, - sequencesPreliminary = True, - sequence_to_use = None, - fallback_date = None): - """ - Generate a filename for the photo or video in string format based on user preferences. - - Returns the name in string format - - Any problems encountered during the generation of the name can be accessed - through the method getProblems() - """ - - if self.sequences: - if sequence_to_use is not None: - sequence = sequence_to_use - elif sequencesPreliminary: - sequence = self.sequences.getPrelimSequence() - else: - sequence = self.sequences.getFinalSequence() - else: - sequence = 0 - - return self._generateName(metadata, existingFilename, stripCharacters, subfolder, - stripInitialPeriodFromExtension, sequence, fallback_date) - - def generateNameSequencePossibilities(self, metadata, 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(metadata, 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 in [SEPARATOR, JOB_CODE]: - 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 - -def getVideoMetadataComponent(video): - """ - Returns portion of video / subfolder name based on the metadata - - This is outside of a class definition because of the inheritence - hierarchy. - """ - - problem = None - if video.L1 == CODEC: - v = video.metadata.codec() - elif video.L1 == WIDTH: - v = video.metadata.width() - elif video.L1 == HEIGHT: - v = video.metadata.height() - elif video.L1 == FPS: - v = video.metadata.framesPerSecond() - elif video.L1 == LENGTH: - v = video.metadata.length() - else: - raise TypeError("Invalid metadata option specified") - if video.L1 in [CODEC]: - if video.L2 == UPPERCASE: - v = v.upper() - elif video.L2 == LOWERCASE: - v = v.lower() - if not v: - video.problem.add_problem(video.component, pn.MISSING_METADATA, _(video.L1)) - return v - -class VideoRenamePreferences(ImageRenamePreferences): - def __init__(self, prefList, parent, fileSequenceLock=None, sequences=None): - self.prefsDefnL0 = DICT_VIDEO_RENAME_L0 - self.defaultPrefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE] - self.defaultRow = self.defaultPrefs - self.stripForwardSlash = True - self.L1DateCheck = VIDEO_DATE - self.component = pn.FILENAME_COMPONENT - ImageRenamePreferences.__init__(self, prefList, parent, fileSequenceLock, sequences) - - def _getMetadataComponent(self): - """ - Returns portion of video / subfolder name based on the metadata - - Note: date time metadata found in _getDateComponent() - """ - return getVideoMetadataComponent(self) - - -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 - self.L1DateCheck = IMAGE_DATE - self.component = pn.SUBFOLDER_COMPONENT - ImageRenamePreferences.__init__(self, prefList, parent) - - self.stripExtraneousWhiteSpace = re.compile(r'\s*%s\s*' % os.sep) - - def generateNameUsingPreferences(self, photo, existingFilename=None, - stripCharacters = False, fallback_date = None): - """ - 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 = ImageRenamePreferences.generateNameUsingPreferences( - self, photo, - existingFilename, stripCharacters, - stripInitialPeriodFromExtension=True, - fallback_date=fallback_date) - # 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:] - - # remove any spaces before and after a directory name - if subfolders and stripCharacters: - subfolders = self.stripExtraneousWhiteSpace.sub(os.sep, subfolders) - - return subfolders - - 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 VideoSubfolderPreferences(SubfolderPreferences): - def __init__(self, prefList, parent): - SubfolderPreferences.__init__(self, prefList, parent) - self.prefsDefnL0 = DICT_VIDEO_SUBFOLDER_L0 - self.defaultPrefs = DEFAULT_VIDEO_SUBFOLDER_PREFS - self.defaultRow = [DATE_TIME, VIDEO_DATE, LIST_DATE_TIME_L2[0]] - self.L1DateCheck = VIDEO_DATE - self.component = pn.SUBFOLDER_COMPONENT - - def _getMetadataComponent(self): - """ - Returns portion of video / subfolder name based on the metadata - - Note: date time metadata found in _getDateComponent() - """ - return getVideoMetadataComponent(self) - -class Sequences: - """ - Holds sequence numbers and letters used in generating filenames. - The same instance of this class is shared among all threads. - """ - 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): - assert(self.assignedSequenceCounter == self.pool[0]) - self.assignedSequenceCounter += 1 - self.pool = self.pool[1:] - #assert(len(self.pool) > 0) - - - - -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/rpdfile.py b/rapid/rpdfile.py new file mode 100644 index 0000000..d9454d7 --- /dev/null +++ b/rapid/rpdfile.py @@ -0,0 +1,304 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 gtk + +import time, datetime + +import multiprocessing, logging +logger = multiprocessing.get_logger() + +import pyexiv2 + +import paths + +from gettext import gettext as _ + +import config +import metadataphoto +import metadatavideo + +import problemnotification as pn + +import thumbnail as tn + + +RAW_EXTENSIONS = ['arw', 'dcr', 'cr2', 'crw', 'dng', 'mos', 'mef', 'mrw', + 'nef', 'orf', 'pef', 'raf', 'raw', 'rw2', 'sr2', 'srw'] + +NON_RAW_IMAGE_EXTENSIONS = ['jpg', 'jpe', 'jpeg', 'tif', 'tiff'] + +PHOTO_EXTENSIONS = RAW_EXTENSIONS + NON_RAW_IMAGE_EXTENSIONS + +if metadatavideo.DOWNLOAD_VIDEO: + # some distros do not include the necessary libraries that Rapid Photo Downloader + # needs to be able to download videos + VIDEO_EXTENSIONS = ['3gp', 'avi', 'm2t', 'mov', 'mp4', 'mpeg','mpg', 'mod', + 'tod'] + VIDEO_THUMBNAIL_EXTENSIONS = ['thm'] +else: + VIDEO_EXTENSIONS = [] + VIDEO_THUMBNAIL_EXTENSIONS = [] + + +FILE_TYPE_PHOTO = 0 +FILE_TYPE_VIDEO = 1 + + +def file_type(file_extension): + """ + Uses file extentsion to determine the type of file - photo or video. + + Returns True if yes, else False. + """ + if file_extension in PHOTO_EXTENSIONS: + return FILE_TYPE_PHOTO + elif file_extension in VIDEO_EXTENSIONS: + return FILE_TYPE_VIDEO + return None + +def get_rpdfile(extension, name, display_name, path, size, + file_system_modification_time, + scan_pid, file_id): + + if extension in VIDEO_EXTENSIONS: + return Video(name, display_name, path, size, + file_system_modification_time, + scan_pid, file_id) + else: + # assume it's a photo - no check for performance reasons (this will be + # called many times) + return Photo(name, display_name, path, size, + file_system_modification_time, + scan_pid, file_id) + +class FileTypeCounter: + def __init__(self): + self._counter = dict() + + def add(self, file_type): + self._counter[file_type] = self._counter.setdefault(file_type, 0) + 1 + + def file_types_present(self): + """ + returns a string to be displayed to the user that can be used + to show if a value refers to photos or videos or both, or just one + of each + """ + + no_videos = self._counter.setdefault(FILE_TYPE_VIDEO, 0) + no_images = self._counter.setdefault(FILE_TYPE_PHOTO, 0) + + if (no_videos > 0) and (no_images > 0): + v = _('photos and videos') + elif (no_videos == 0) and (no_images == 0): + v = _('photos or videos') + elif no_videos > 0: + if no_videos > 1: + v = _('videos') + else: + v = _('video') + else: + if no_images > 1: + v = _('photos') + else: + v = _('photo') + return v + + def count_files(self): + i = 0 + for key in self._counter: + i += self._counter[key] + return i + + def summarize_file_count(self): + #Number of files, e.g. "433 photos and videos" or "23 videos". + #Displayed in the progress bar at the top of the main application + #window. + file_types_present = self.file_types_present() + file_count_summary = _("%(number)s %(filetypes)s") % \ + {'number':self.count_files(), + 'filetypes': file_types_present} + return (file_count_summary, file_types_present) + +class RPDFile: + """ + Base class for photo or video file, with metadata + """ + + def __init__(self, name, display_name, path, size, + file_system_modification_time, + scan_pid, file_id): + + self.path = path + + self.name = name + self.display_name = display_name + + self.full_file_name = os.path.join(path, name) + + self.size = size # type int + + self.modification_time = file_system_modification_time + + self.status = config.STATUS_NOT_DOWNLOADED + self.problem = None # class Problem in problemnotifcation.py + + self._assign_file_type() + + self.scan_pid = scan_pid + self.file_id = file_id + self.unique_id = str(scan_pid) + ":" + file_id + + self.problem = None + self.job_code = None + + # indicates whether to generate a thumbnail during the copy + # files process + self.generate_thumbnail = False + + # generated values + + self.temp_full_file_name = '' + self.download_start_time = None + + self.download_subfolder = '' + self.download_path = '' + self.download_name = '' + self.download_full_file_name = '' + + self.metadata = None + + # Values that will be inserted in download process -- + # (commented out because they're not needed until then) + + #self.sequences = None + #self.download_folder + #self.subfolder_pref_list = [] + #self.name_pref_list = [] + #strip_characters = False + + + def _assign_file_type(self): + self.file_type = None + + def initialize_problem(self): + self.problem = pn.Problem() + # these next values are used to display in the error log window + # the information in them can vary from other forms of display of errors + self.error_title = self.error_msg = self.error_extra_detail = '' + + def has_problem(self): + if self.problem is None: + return False + else: + return self.problem.has_problem() + + def add_problem(self, component, problem_definition, *args): + if self.problem is None: + self.initialize_problem() + self.problem.add_problem(component, problem_definition, *args) + + def add_extra_detail(self, extra_detail, *args): + self.problem.add_extra_detail(extra_detail, *args) + + + +#~ exif_tags_needed = ('Exif.Photo.FNumber', + #~ 'Exif.Photo.ISOSpeedRatings', + #~ 'Exif.Photo.ExposureTime', + #~ 'Exif.Photo.FocalLength', + #~ 'Exif.Image.Make', + #~ 'Exif.Image.Model', + #~ 'Exif.Canon.SerialNumber', + #~ 'Exif.Nikon3.SerialNumber' + #~ 'Exif.OlympusEq.SerialNumber', + #~ 'Exif.Olympus.SerialNumber', + #~ 'Exif.Olympus.SerialNumber2', + #~ 'Exif.Panasonic.SerialNumber', + #~ 'Exif.Fujifilm.SerialNumber', + #~ 'Exif.Image.CameraSerialNumber', + #~ 'Exif.Nikon3.ShutterCount', + #~ 'Exif.Canon.FileNumber', + #~ 'Exif.Canon.ImageNumber', + #~ 'Exif.Canon.OwnerName', + #~ 'Exif.Photo.DateTimeOriginal', + #~ 'Exif.Image.DateTime', + #~ 'Exif.Photo.SubSecTimeOriginal', + #~ 'Exif.Image.Orientation' + #~ ) + +class Photo(RPDFile): + + title = _("photo") + title_capitalized = _("Photo") + + def _assign_file_type(self): + self.file_type = FILE_TYPE_PHOTO + + def load_metadata(self): + + self.metadata = metadataphoto.MetaData(self.full_file_name) + try: + self.metadata.read() + except: + logger.warning("Could not read metadata from %s" % self.full_file_name) + return False + else: + return True + + +class Video(RPDFile): + + title = _("video") + title_capitalized = _("Video") + + def _assign_file_type(self): + self.file_type = FILE_TYPE_VIDEO + + def load_metadata(self): + self.metadata = metadatavideo.VideoMetaData(self.full_file_name) + return True + +class SamplePhoto(Photo): + def __init__(self, sample_name='IMG_0524.CR2', sequences=None): + Photo.__init__(self, name=sample_name, + display_name=sample_name, + path='/media/EOS_DIGITAL/DCIM/100EOS5D', + size=23516764, + file_system_modification_time=time.time(), + scan_pid=2033, + file_id='9873afe') + self.sequences = sequences + self.metadata = metadataphoto.DummyMetaData() + self.download_start_time = datetime.datetime.now() + +class SampleVideo(Video): + def __init__(self, sample_name='MVI_1379.MOV', sequences=None): + Video.__init__(self, name=sample_name, + display_name=sample_name, + path='/media/EOS_DIGITAL/DCIM/100EOS5D', + size=823513764, + file_system_modification_time=time.time(), + scan_pid=2033, + file_id='9873qrsfe') + self.sequences = sequences + self.metadata = metadatavideo.DummyMetaData(filename=sample_name) + self.download_start_time = datetime.datetime.now() diff --git a/rapid/rpdmultiprocessing.py b/rapid/rpdmultiprocessing.py new file mode 100644 index 0000000..7fdd252 --- /dev/null +++ b/rapid/rpdmultiprocessing.py @@ -0,0 +1,25 @@ +# -*- coding: latin1 -*- +### Copyright (C) 2007, 2008, 2009, 2010, 2011 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 + +CONN_PARTIAL = 0 +CONN_COMPLETE = 1 + +MSG_BYTES = 0 +MSG_FILE = 1 +MSG_TEMP_DIRS = 2 + +MSG_SEQUENCE_VALUE = 0 diff --git a/rapid/scan.py b/rapid/scan.py new file mode 100755 index 0000000..e55f43d --- /dev/null +++ b/rapid/scan.py @@ -0,0 +1,170 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 multiprocessing + +import gio +import gtk + +import pyexiv2 + +import rpdmultiprocessing as rpdmp +import rpdfile + + +import logging +logger = multiprocessing.get_logger() + +# python whitespace is significant - don't remove the leading whitespace on +# the second line + +file_attributes = "standard::name,standard::display-name,\ +standard::type,standard::size,time::modified,access::can-read,id::file" + + + +class Scan(multiprocessing.Process): + + """Scans the given path for files of a specified type. + + Returns results in batches, finishing with a total of the size of all the + files in bytes. + """ + + def __init__(self, path, batch_size, generate_folder, results_pipe, + terminate_queue, run_event): + + """Setup values needed to conduct the scan. + + 'path' is a string of the path to be scanned, which is passed to gio. + + 'batch_size' is the number of files that should be sent back to the + calling function at one time. + + 'results_pipe' is a connection on which to send the results. + + 'terminate_queue' is a queue whose sole purpose is to notify the + process that it should terminate and not return any results. + + 'run_event' is an Event that is used to temporarily halt execution. + + """ + + multiprocessing.Process.__init__(self) + self.path = path + self.results_pipe = results_pipe + self.terminate_queue = terminate_queue + self.run_event = run_event + self.batch_size = batch_size + self.generate_folder = generate_folder + self.counter = 0 + self.files = [] + self.file_type_counter = rpdfile.FileTypeCounter() + + + def _gio_scan(self, path, file_size_sum): + """recursive function to scan a directory and its subdirectories + for photos and possibly videos""" + + children = path.enumerate_children(file_attributes) + + for child in children: + + # pause if instructed by the caller + self.run_event.wait() + + if not self.terminate_queue.empty(): + x = self.terminate_queue.get() + # terminate immediately + logger.info("terminating scan...") + self.files = [] + return None + + # only collect files and scan in directories we can actually read + # cannot assume that users will download only from memory cards + + if child.get_attribute_boolean(gio.FILE_ATTRIBUTE_ACCESS_CAN_READ): + file_type = child.get_file_type() + name = child.get_name() + if file_type == gio.FILE_TYPE_DIRECTORY: + file_size_sum = self._gio_scan(path.get_child(name), + file_size_sum) + if file_size_sum is None: + return None + + elif file_type == gio.FILE_TYPE_REGULAR: + ext = os.path.splitext(name)[1].lower()[1:] + + file_type = rpdfile.file_type(ext) + if file_type is not None: + # count how many files of each type are included + # e.g. photo, video + self.file_type_counter.add(file_type) + self.counter += 1 + display_name = child.get_display_name() + size = child.get_size() + modification_time = child.get_modification_time() + file_id = child.get_attribute_string( + gio.FILE_ATTRIBUTE_ID_FILE) + scanned_file = rpdfile.get_rpdfile(ext, + name, + display_name, + path.get_path(), + size, + modification_time, + self.pid, + file_id) + + if self.generate_folder: + # this dramatically slows scanning speed, and it + # is unlikely this will be called this early in the + # workflow + scanned_file.read_metadata() + + self.files.append(scanned_file) + + if self.counter == self.batch_size: + # send batch of results + self.results_pipe.send((rpdmp.CONN_PARTIAL, + self.files)) + self.files = [] + self.counter = 0 + + file_size_sum += size + + return file_size_sum + + + def run(self): + """start the actual scan.""" + source = gio.File(self.path) + try: + size = self._gio_scan(source, 0) + except gio.Error, inst: + logger.error("Error while scanning %s: %s", self.path, inst) + size = None + + if size is not None: + if self.counter > 0: + # send any remaining results + self.results_pipe.send((rpdmp.CONN_PARTIAL, self.files)) + self.results_pipe.send((rpdmp.CONN_COMPLETE, (size, + self.file_type_counter, self.pid))) + self.results_pipe.close() diff --git a/rapid/subfolderfile.py b/rapid/subfolderfile.py new file mode 100644 index 0000000..7e4a495 --- /dev/null +++ b/rapid/subfolderfile.py @@ -0,0 +1,474 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 + +""" +Generates names for files and folders. + +Runs a daemon process. +""" + +import os, datetime, collections + +import gio +import multiprocessing +import logging +logger = multiprocessing.get_logger() + + +import rpdfile +import rpdmultiprocessing as rpdmp +import generatename as gn +import problemnotification as pn +import prefsrapid +import config + +from gettext import gettext as _ + +class SyncRawJpeg: + def __init__(self): + self.photos = {} + + def add_download(self, name, extension, date_time, sub_seconds, sequence_number_used): + if name not in self.photos: + self.photos[name] = ([extension], date_time, sub_seconds, sequence_number_used) + else: + if extension not in self.photos[name][0]: + self.photos[name][0].append(extension) + + + def matching_pair(self, name, extension, date_time, sub_seconds): + """Checks to see if the image matches an image that has already been downloaded. + Image name (minus extension), exif date time, and exif subseconds are checked. + + Returns -1 and a sequence number if the name, extension, and exif values match (i.e. it has already been downloaded) + Returns 0 and a sequence number if name and exif values match, but the extension is different (i.e. a matching RAW + JPG image) + Returns -99 and a sequence number of None if photos detected with the same filenames, but taken at different times + Returns 1 and a sequence number of None if no match""" + + if name in self.photos: + if self.photos[name][1] == date_time and self.photos[name][2] == sub_seconds: + if extension in self.photos[name][0]: + return (-1, self.photos[name][3]) + else: + return (0, self.photos[name][3]) + else: + return (-99, None) + return (1, None) + + def ext_exif_date_time(self, name): + """Returns first extension, exif date time and subseconds data for the already downloaded photo""" + return (self.photos[name][0][0], self.photos[name][1], self.photos[name][2]) + +def time_subseconds_human_readable(date, subseconds): + return _("%(hour)s:%(minute)s:%(second)s:%(subsecond)s") % \ + {'hour':date.strftime("%H"), + 'minute':date.strftime("%M"), + 'second':date.strftime("%S"), + 'subsecond': subseconds} + +def load_metadata(rpd_file): + """ + Loads the metadata for the file. Returns True if operation succeeded, false + otherwise + """ + if rpd_file.metadata is None: + if not rpd_file.load_metadata(): + # Error in reading metadata + rpd_file.add_problem(None, pn.CANNOT_DOWNLOAD_BAD_METADATA, {'filetype': rpd_file.title_capitalized}) + return False + return True + + +def _generate_name(generator, rpd_file): + + do_generation = True + if rpd_file.file_type == rpdfile.FILE_TYPE_PHOTO: + do_generation = load_metadata(rpd_file) + else: + if rpd_file.metadata is None: + rpd_file.load_metadata() + + if do_generation: + value = generator.generate_name(rpd_file) + if value is None: + value = '' + else: + value = '' + + return value + +def generate_subfolder(rpd_file): + + if rpd_file.file_type == rpdfile.FILE_TYPE_PHOTO: + generator = gn.PhotoSubfolder(rpd_file.subfolder_pref_list) + else: + generator = gn.VideoSubfolder(rpd_file.subfolder_pref_list) + + rpd_file.download_subfolder = _generate_name(generator, rpd_file) + return rpd_file + +def generate_name(rpd_file): + do_generation = True + + if rpd_file.file_type == rpdfile.FILE_TYPE_PHOTO: + generator = gn.PhotoName(rpd_file.name_pref_list) + else: + generator = gn.VideoName(rpd_file.name_pref_list) + + rpd_file.download_name = _generate_name(generator, rpd_file) + return rpd_file + + +class SubfolderFile(multiprocessing.Process): + def __init__(self, results_pipe, sequence_values): + multiprocessing.Process.__init__(self) + self.daemon = True + self.results_pipe = results_pipe + + self.downloads_today = sequence_values[0] + self.downloads_today_date = sequence_values[1] + self.day_start = sequence_values[2] + self.refresh_downloads_today = sequence_values[3] + self.stored_sequence_no = sequence_values[4] + self.uses_stored_sequence_no = sequence_values[5] + self.uses_session_sequece_no = sequence_values[6] + self.uses_sequence_letter = sequence_values[7] + + logger.debug("Start of day is set to %s", self.day_start.value) + + def progress_callback_no_update(self, amount_downloaded, total): + pass + + def file_exists(self, rpd_file, identifier=None): + """ + Notify user that the download file already exists + """ + # get information on when the existing file was last modified + try: + modification_time = os.path.getmtime(rpd_file.download_full_file_name) + dt = datetime.datetime.fromtimestamp(modification_time) + date = dt.strftime("%x") + time = dt.strftime("%X") + except: + logger.warning("Could not determine the file modification time of %s", + rpd_file.download_full_file_name) + date = time = '' + + if not identifier: + rpd_file.add_problem(None, pn.FILE_ALREADY_EXISTS_NO_DOWNLOAD, + {'filetype':rpd_file.title_capitalized}) + rpd_file.add_extra_detail(pn.EXISTING_FILE, + {'filetype': rpd_file.title, + 'date': date, 'time': time}) + rpd_file.status = config.STATUS_DOWNLOAD_FAILED + rpd_file.error_extra_detail = pn.extra_detail_definitions[pn.EXISTING_FILE] % \ + {'date':date, 'time':time, 'filetype': rpd_file.title} + else: + rpd_file.add_problem(None, pn.UNIQUE_IDENTIFIER_ADDED, + {'filetype':rpd_file.title_capitalized}) + rpd_file.add_extra_detail(pn.UNIQUE_IDENTIFIER, + {'identifier': identifier, + 'filetype': rpd_file.title, + 'date': date, 'time': time}) + rpd_file.status = config.STATUS_DOWNLOADED_WITH_WARNING + rpd_file.error_extra_detail = pn.extra_detail_definitions[pn.UNIQUE_IDENTIFIER] % \ + {'identifier': identifier, 'filetype': rpd_file.title, + 'date': date, 'time': time} + rpd_file.error_title = rpd_file.problem.get_title() + rpd_file.error_msg = _("Source: %(source)s\nDestination: %(destination)s") \ + % {'source': rpd_file.full_file_name, + 'destination': rpd_file.download_full_file_name} + return rpd_file + + def download_failure_file_error(self, rpd_file, inst): + """ + Handle cases where file failed to download + """ + rpd_file.add_problem(None, pn.DOWNLOAD_COPYING_ERROR, {'filetype': rpd_file.title}) + rpd_file.add_extra_detail(pn.DOWNLOAD_COPYING_ERROR_DETAIL, inst) + rpd_file.status = config.STATUS_DOWNLOAD_FAILED + logger.error("Failed to create file %s: %s", rpd_file.download_full_file_name, inst) + + rpd_file.error_title = rpd_file.problem.get_title() + rpd_file.error_msg = _("%(problem)s\nFile: %(file)s") % \ + {'problem': rpd_file.problem.get_problems(), + 'file': rpd_file.full_file_name} + + return rpd_file + + def same_name_different_exif(self, sync_photo_name, rpd_file): + """Notify the user that a file was already downloaded with the same name, but the exif information was different""" + i1_ext, i1_date_time, i1_subseconds = self.sync_raw_jpeg.ext_exif_date_time(sync_photo_name) + detail = {'image1': "%s%s" % (sync_photo_name, i1_ext), + 'image1_date': i1_date_time.strftime("%x"), + 'image1_time': time_subseconds_human_readable(i1_date_time, i1_subseconds), + 'image2': rpd_file.name, + 'image2_date': rpd_file.metadata.date_time().strftime("%x"), + 'image2_time': time_subseconds_human_readable( + rpd_file.metadata.date_time(), + rpd_file.metadata.sub_seconds())} + rpd_file.add_problem(None, pn.SAME_FILE_DIFFERENT_EXIF, detail) + + rpd_file.error_title = _('Photos detected with the same filenames, but taken at different times') + rpd_file.error_msg = pn.problem_definitions[pn.SAME_FILE_DIFFERENT_EXIF][1] % detail + rpd_file.status = config.STATUS_DOWNLOADED_WITH_WARNING + return rpd_file + + + def run(self): + """ + Get subfolder and name. + Attempt to move the file from it's temporary directory. + If successful, increment sequence values. + Report any success or failure. + """ + i = 0 + download_count = 0 + + duplicate_files = {} + + + # Track downloads today, using a class whose purpose is to + # take the value in the user prefs, increment, and then be used + # to update the prefs (which can only happen via the main process) + self.downloads_today_tracker = prefsrapid.DownloadsTodayTracker( + day_start = self.day_start.value, + downloads_today = self.downloads_today.value, + downloads_today_date = self.downloads_today_date.value) + + # Track sequences using shared downloads today and stored sequence number + # (shared with main process) + self.sequences = gn.Sequences(self.downloads_today_tracker, + self.stored_sequence_no.value) + + self.sync_raw_jpeg = SyncRawJpeg() + + + while True: + logger.debug("Finished %s. Getting next task.", download_count) + + task = self.results_pipe.recv() + + # rename file and move to generated subfolder + download_succeeded, download_count, rpd_file = task + + move_succeeded = False + + + if download_succeeded: + temp_file = gio.File(rpd_file.temp_full_file_name) + + synchronize_raw_jpg_failed = False + if not (rpd_file.synchronize_raw_jpg and + rpd_file.file_type == rpdfile.FILE_TYPE_PHOTO): + synchronize_raw_jpg = False + sequence_to_use = None + else: + synchronize_raw_jpg = True + sync_photo_name, sync_photo_ext = os.path.splitext(rpd_file.name) + if not load_metadata(rpd_file): + synchronize_raw_jpg_failed = True + else: + j, sequence_to_use = self.sync_raw_jpeg.matching_pair( + name=sync_photo_name, extension=sync_photo_ext, + date_time=rpd_file.metadata.date_time(), + sub_seconds=rpd_file.metadata.sub_seconds()) + if j == -1: + # this exact file has already been downloaded (same extension, same filename, and same exif date time subsecond info) + if (rpd_file.download_conflict_resolution <> + config.ADD_UNIQUE_IDENTIFIER): + rpd_file.add_problem(None, pn.FILE_ALREADY_DOWNLOADED, {'filetype': rpd_file.title_capitalized}) + rpd_file.error_title = _('Photo has already been downloaded') + rpd_file.error_msg = _("Source: %(source)s") % {'source': rpd_file.full_file_name} + rpd_file.status = config.STATUS_DOWNLOAD_FAILED + synchronize_raw_jpg_failed = True + else: + self.sequences.set_matched_sequence_value(sequence_to_use) + if j == -99: + rpd_file = self.same_name_different_exif(sync_photo_name, rpd_file) + + if synchronize_raw_jpg_failed: + generation_succeeded = False + else: + # Generate subfolder name and new file name + generation_succeeded = True + rpd_file = generate_subfolder(rpd_file) + if rpd_file.download_subfolder: + + if self.refresh_downloads_today.value: + # overwrite downloads today value tracked here, + # as user has modified their preferences + self.downloads_today_tracker.set_raw_downloads_today_from_int(self.downloads_today.value) + self.downloads_today_tracker.set_raw_downloads_today_date(self.downloads_today_date.value) + self.downloads_today_tracker.day_start = self.day_start.value + self.refresh_downloads_today.value = False + + # update whatever the stored value is + self.sequences.stored_sequence_no = self.stored_sequence_no.value + rpd_file.sequences = self.sequences + + # generate the file name + rpd_file = generate_name(rpd_file) + + if rpd_file.has_problem(): + rpd_file.status = config.STATUS_DOWNLOADED_WITH_WARNING + rpd_file.error_title = rpd_file.problem.get_title() + rpd_file.error_msg = _("%(problem)s\nFile: %(file)s") % \ + {'problem': rpd_file.problem.get_problems(), + 'file': rpd_file.full_file_name} + + # Check for any errors + if not rpd_file.download_subfolder or not rpd_file.download_name: + if not rpd_file.download_subfolder and not rpd_file.download_name: + area = _("subfolder and filename") + elif not rpd_file.download_name: + area = _("filename") + else: + area = _("subfolder") + rpd_file.add_problem(None, pn.ERROR_IN_NAME_GENERATION, {'filetype': rpd_file.title_capitalized, 'area': area}) + rpd_file.add_extra_detail(pn.NO_DATA_TO_NAME, {'filetype': area}) + generation_succeeded = False + rpd_file.status = config.STATUS_DOWNLOAD_FAILED + + rpd_file.error_title = rpd_file.problem.get_title() + rpd_file.error_msg = _("%(problem)s\nFile: %(file)s") % \ + {'problem': rpd_file.problem.get_problems(), + 'file': rpd_file.full_file_name} + + + if generation_succeeded: + rpd_file.download_path = os.path.join(rpd_file.download_folder, rpd_file.download_subfolder) + rpd_file.download_full_file_name = os.path.join(rpd_file.download_path, rpd_file.download_name) + + subfolder = gio.File(path=rpd_file.download_path) + + # Create subfolder if it does not exist. + # It is possible to skip the query step, and just try to create + # the directories and ignore the error of it already existing - + # but it takes twice as long to fail with an error than just + # run the straight query + + if not subfolder.query_exists(cancellable=None): + try: + subfolder.make_directory_with_parents(cancellable=gio.Cancellable()) + except gio.Error, inst: + # The directory may have been created by another process + # between the time it takes to query and the time it takes + # to create a new directory. Ignore such errors. + if inst.code <> gio.ERROR_EXISTS: + logger.error("Failed to create download subfolder: %s", rpd_file.download_path) + logger.error(inst) + rpd_file.error_title = _("Failed to create download subfolder") + rpd_file.error_msg = _("Path: %s") % rpd_file.download_path + + # Move temp file to subfolder + + download_file = gio.File(rpd_file.download_full_file_name) + + add_unique_identifier = False + try: + temp_file.move(download_file, self.progress_callback_no_update, cancellable=None) + move_succeeded = True + if rpd_file.status <> config.STATUS_DOWNLOADED_WITH_WARNING: + rpd_file.status = config.STATUS_DOWNLOADED + except gio.Error, inst: + if inst.code == gio.ERROR_EXISTS: + if (rpd_file.download_conflict_resolution == + config.ADD_UNIQUE_IDENTIFIER): + add_unique_identifier = True + else: + rpd_file = self.file_exists(rpd_file) + else: + rpd_file = self.download_failure_file_error(rpd_file, inst) + + if add_unique_identifier: + name = os.path.splitext(rpd_file.download_name) + full_name = rpd_file.download_full_file_name + suffix_already_used = True + while suffix_already_used: + duplicate_files[full_name] = duplicate_files.get( + full_name, 0) + 1 + identifier = '_%s' % duplicate_files[full_name] + rpd_file.download_name = name[0] + identifier + name[1] + rpd_file.download_full_file_name = os.path.join( + rpd_file.download_path, + rpd_file.download_name) + download_file = gio.File( + rpd_file.download_full_file_name) + + try: + temp_file.move(download_file, self.progress_callback_no_update, cancellable=None) + move_succeeded = True + suffix_already_used = False + rpd_file = self.file_exists(rpd_file, identifier) + logger.error("%s: %s - %s", rpd_file.full_file_name, + rpd_file.problem.get_title(), + rpd_file.problem.get_problems()) + except gio.Error, inst: + if inst.code <> gio.ERROR_EXISTS: + rpd_file = self.download_failure_file_error(rpd_file, inst) + + + + logger.debug("Finish processing file: %s", download_count) + + if move_succeeded: + if synchronize_raw_jpg: + if sequence_to_use is None: + sequence = self.sequences.create_matched_sequences() + else: + sequence = sequence_to_use + self.sync_raw_jpeg.add_download(name=sync_photo_name, + extension=sync_photo_ext, + date_time=rpd_file.metadata.date_time(), + sub_seconds=rpd_file.metadata.sub_seconds(), + sequence_number_used=sequence) + if sequence_to_use is None: + if self.uses_session_sequece_no.value or self.uses_sequence_letter.value: + self.sequences.increment( + self.uses_session_sequece_no.value, + self.uses_sequence_letter.value) + if self.uses_stored_sequence_no.value: + self.stored_sequence_no.value += 1 + self.downloads_today_tracker.increment_downloads_today() + self.downloads_today.value = self.downloads_today_tracker.get_raw_downloads_today() + self.downloads_today_date.value = self.downloads_today_tracker.get_raw_downloads_today_date() + + if not move_succeeded: + logger.error("%s: %s - %s", rpd_file.full_file_name, + rpd_file.problem.get_title(), + rpd_file.problem.get_problems()) + try: + temp_file.delete(cancellable=None) + except gio.Error, inst: + logger.error("Failed to delete temporary file %s", rpd_file.temp_full_file_name) + logger.error(inst) + + + + + + rpd_file.metadata = None #purge metadata, as it cannot be pickled + rpd_file.sequences = None + self.results_pipe.send((move_succeeded, rpd_file,)) + + i += 1 + + + diff --git a/rapid/tableplusminus.py b/rapid/tableplusminus.py index ab7e7c1..5713474 100644 --- a/rapid/tableplusminus.py +++ b/rapid/tableplusminus.py @@ -44,15 +44,15 @@ class TablePlusMinus(gtk.Table): 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 + self.extra_cols = 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 + self.extra_cols = 3 # representing minus and plus buttons, and info label # no of columns NOT including the + and - buttons - self.pm_noColumns = columns + self.pm_no_columns = columns # how many rows there are in the gtk.Table - self.pm_noRows = rows + self.pm_no_rows = rows # list of widgets in the gtk.Table self.pm_rows = [] # dict of callback ids for minus and plus buttons @@ -67,39 +67,39 @@ class TablePlusMinus(gtk.Table): 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] + def _set_minus_button_sensitivity(self): + button = self.pm_rows[0][self.pm_no_columns] if len(self.pm_rows) == 1: button.set_sensitive(False) else: button.set_sensitive(True) - def _createMinusPlusButtons(self, rowPosition): + def _create_minus_plus_buttons(self, row_position): 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) + self._create_callback(plus_button, row_position, '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) + self._create_callback(minus_button, row_position, 'clicked', self.on_minus_button_clicked) return minus_button, plus_button def append(self, row): - self.insertAfter(len(self.pm_rows)-1, row) + self.insert_after(len(self.pm_rows)-1, row) - def _getMinusAndPlusButtonsForRow(self, rowPosition): + def _get_minus_and_plus_buttons_for_row(self, row_position): """ - Return as a tuple minus and plus buttons for the row specified by rowPosition + Return as a tuple minus and plus buttons for the row specified by row_position """ - return (self.pm_rows[rowPosition][self.pm_noColumns], self.pm_rows[rowPosition][self.pm_noColumns+1]) + return (self.pm_rows[row_position][self.pm_no_columns], self.pm_rows[row_position][self.pm_no_columns+1]) - def removeRow(self, rowPosition): + def remove_row(self, row_position): # remove widgets from table - for col in range(self.pm_noColumns + self.extraCols): - widget = self.pm_rows[rowPosition][col] + for col in range(self.pm_no_columns + self.extra_cols): + widget = self.pm_rows[row_position][col] if widget: self.remove(widget) if self.pm_callbacks.has_key(widget): @@ -108,61 +108,61 @@ class TablePlusMinus(gtk.Table): # reposition existing rows in gtk.Table - self._moveRows(-1, rowPosition + 1) + self._move_rows(-1, row_position + 1) # remove row from list of rows - del self.pm_rows[rowPosition] + del self.pm_rows[row_position] - self._setMinusButtonSensitivity() - self.pm_noRows -= 1 - self.resize(self.pm_noRows, self.pm_noColumns + self.extraCols) - self._printDebugInfo() + self._set_minus_button_sensitivity() + self.pm_no_rows -= 1 + self.resize(self.pm_no_rows, self.pm_no_columns + self.extra_cols) + self._print_debug_info() - def _createCallback(self, widget, rowPosition, callbackType = None, callbackMethod=None): - if callbackType: - self.pm_callbacks[widget] = widget.connect(callbackType, callbackMethod, rowPosition) + def _create_callback(self, widget, row_position, callback_type = None, callbackMethod=None): + if callback_type: + self.pm_callbacks[widget] = widget.connect(callback_type, callbackMethod, row_position) else: name = widget.get_name() if name == 'GtkComboBox': - self.pm_callbacks[widget] = widget.connect("changed", self.on_combobox_changed, rowPosition) + self.pm_callbacks[widget] = widget.connect("changed", self.on_combobox_changed, row_position) elif name == 'GtkEntry': - self.pm_callbacks[widget] = widget.connect("changed", self.on_entry_changed, rowPosition) + self.pm_callbacks[widget] = widget.connect("changed", self.on_entry_changed, row_position) - def _moveRows(self, adjustment, startRow, endRow = -1): + def _move_rows(self, adjustment, start_row, end_row = -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. + Starts at row start_row and ends at row end_row. If end_row == -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 end_row == -1: + end_row = len(self.pm_rows) + for r in range(start_row, end_row): 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)) + print "Row %s becomes row %s" % (self.pm_rows[r][self.pm_no_columns + 2].get_label(), r + adjustment) + self.pm_rows[r][self.pm_no_columns + 2].set_label(str(r + adjustment)) - for col in range(self.pm_noColumns + self.extraCols): + for col in range(self.pm_no_columns + self.extra_cols): 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) + if col == self.pm_no_columns: + self._create_callback(widget, r + adjustment, 'clicked', self.on_minus_button_clicked) + elif col == self.pm_no_columns + 1: + self._create_callback(widget, r + adjustment, 'clicked', self.on_plus_button_clicked) else: - self._createCallback(widget, r + adjustment) + self._create_callback(widget, r + adjustment) - def _printDebugInfo(self): + def _print_debug_info(self): if self.debug: print "\nRows in internal list: %s\nTable rows: %s" % \ - (len(self.pm_rows), self.pm_noRows) + (len(self.pm_rows), self.pm_no_rows) - if len(self.pm_rows) <> self.pm_noRows: + if len(self.pm_rows) <> self.pm_no_rows: print "|\n\\\n --> Unequal no. of rows" @@ -172,42 +172,42 @@ class TablePlusMinus(gtk.Table): """ 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: + if left_attach >= self.pm_no_columns and left_attach <= self.pm_no_columns + 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): + def insert_after(self, row_position, row): """ - Inserts row into the table at row following rowPosition + Inserts row into the table at row following row_position """ #is table big enough? - self.checkTableRowsAndAdjust() + self.check_table_rows_and_adjust() #move (reattach) other widgets & readjust connect - self._moveRows(1, rowPosition + 1) + self._move_rows(1, row_position + 1) # insert row - for col in range(self.pm_noColumns): + for col in range(self.pm_no_columns): widget = row[col] if widget: - self._createCallback(widget, rowPosition+1) - self.attach(widget, col, col+1, rowPosition+1, rowPosition+2) + self._create_callback(widget, row_position+1) + self.attach(widget, col, col+1, row_position+1, row_position+2) - minus_button, plus_button = self._createMinusPlusButtons(rowPosition+1) + minus_button, plus_button = self._create_minus_plus_buttons(row_position+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) + self.attach(minus_button, self.pm_no_columns, self.pm_no_columns+1, row_position+1, row_position+2) + self.attach(plus_button, self.pm_no_columns+1, self.pm_no_columns+2, row_position+1, row_position+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) + label = gtk.Label(str(row_position+1)) + self.attach(label, self.pm_no_columns+2, self.pm_no_columns+3, row_position+1, row_position+2) row.append(label) @@ -217,66 +217,66 @@ class TablePlusMinus(gtk.Table): #adjust internal reference table - self.pm_rows.insert(rowPosition + 1, row) + self.pm_rows.insert(row_position + 1, row) - self._setMinusButtonSensitivity() + self._set_minus_button_sensitivity() - self._printDebugInfo() + self._print_debug_info() - 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) + def check_table_rows_and_adjust(self, no_rows_to_add=1, adjust_rows=True): + no_rows_ok = True + if len(self.pm_rows) + no_rows_to_add > self.pm_no_rows: + if adjust_rows: + extra_rows_to_add = len(self.pm_rows) + no_rows_to_add - self.pm_no_rows + self.pm_no_rows += extra_rows_to_add + self.resize(self.pm_no_rows, self.pm_no_columns + self.extra_cols) else: - noRowsOk = False - return noRowsOk + no_rows_ok = False + return no_rows_ok - def getDefaultRow(self): + def get_default_row(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 + return [None] * self.pm_no_columns - def on_combobox_changed(self, widget, rowPosition): + def on_combobox_changed(self, widget, row_position): """ Callback for combobox that is expected to be implemented in derived class """ pass - def on_entry_changed(self, widget, rowPosition): + def on_entry_changed(self, widget, row_position): """ Callback for entry that is expected to be implemented in derived class """ pass - def _debugButtonPressed(self, buttonText, rowPosition): + def _debug_button_pressed(self, buttonText, row_position): if self.debug: t = datetime.datetime.now().strftime("%H:%M:%S") - print "\n****\n%s\n\n%s clicked at %s" %(t, buttonText, rowPosition) + print "\n****\n%s\n\n%s clicked at %s" %(t, buttonText, row_position) - def on_minus_button_clicked(self, widget, rowPosition): - self._debugButtonPressed("Minus", rowPosition) - self.removeRow(rowPosition) - self.on_rowDeleted(rowPosition) + def on_minus_button_clicked(self, widget, row_position): + self._debug_button_pressed("Minus", row_position) + self.remove_row(row_position) + self.on_row_deleted(row_position) - def on_plus_button_clicked(self, widget, rowPosition): - self._debugButtonPressed("Plus", rowPosition) - self.insertAfter(rowPosition, self.getDefaultRow()) - self.on_rowAdded(rowPosition) + def on_plus_button_clicked(self, widget, row_position): + self._debug_button_pressed("Plus", row_position) + self.insert_after(row_position, self.get_default_row()) + self.on_row_added(row_position) - def on_rowAdded(self, rowPosition): + def on_row_added(self, row_position): """ Expected to be implemented in derived class """ pass - def on_rowDeleted(self, rowPosition): + def on_row_deleted(self, row_position): """ Expected to be implemented in derived class """ diff --git a/rapid/thumbnail.py b/rapid/thumbnail.py new file mode 100644 index 0000000..7a41e54 --- /dev/null +++ b/rapid/thumbnail.py @@ -0,0 +1,392 @@ +#!/usr/bin/python +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2011 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 multiprocessing +import types +import os + +import gtk + +import paths + +from PIL import Image +import cStringIO +import tempfile +import subprocess + +import rpdfile + +import rpdmultiprocessing as rpdmp +from utilities import image_to_pixbuf, pixbuf_to_image +import pyexiv2 + +from filmstrip import add_filmstrip + +import logging +logger = multiprocessing.get_logger() + + +def get_stock_photo_image(): + length = min(gtk.gdk.screen_width(), gtk.gdk.screen_height()) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(paths.share_dir('glade3/photo.svg'), length, length) + image = pixbuf_to_image(pixbuf) + return image + +def get_stock_photo_image_icon(): + image = Image.open(paths.share_dir('glade3/photo66.png')) + image = image.convert("RGBA") + return image + +def get_stock_video_image(): + length = min(gtk.gdk.screen_width(), gtk.gdk.screen_height()) + pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(paths.share_dir('glade3/video.svg'), length, length) + image = pixbuf_to_image(pixbuf) + return image + +def get_stock_video_image_icon(): + image = Image.open(paths.share_dir('glade3/video66.png')) + image = image.convert("RGBA") + return image + + +class PhotoIcons(): + stock_thumbnail_image_icon = get_stock_photo_image_icon() + +class VideoIcons(): + stock_thumbnail_image_icon = get_stock_video_image_icon() + +def upsize_pil(image, size): + width_max = size[0] + height_max = size[1] + width_orig = float(image.size[0]) + height_orig = float(image.size[1]) + 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 + + return image.resize((width, height), Image.ANTIALIAS) + +def downsize_pil(image, box, fit=False): + """Downsample the PIL image. + image: Image - an Image-object + box: tuple(x, y) - the bounding box of the result image + fix: boolean - crop the image to fill the box + + Code adpated from example by Christian Harms + Source: http://united-coders.com/christian-harms/image-resizing-tips-every-coder-should-know + """ + #preresize image with factor 2, 4, 8 and fast algorithm + factor = 1 + logger.debug("Image size %sx%s", image.size[0], image.size[1]) + logger.debug("Box size %sx%s", box[0],box[1]) + while image.size[0]/factor > 2*box[0] and image.size[1]*2/factor > 2*box[1]: + factor *=2 + if factor > 1: + logger.debug("quick resize %sx%s", image.size[0]/factor, image.size[1]/factor) + image.thumbnail((image.size[0]/factor, image.size[1]/factor), Image.NEAREST) + logger.debug("did first thumbnail") + + #calculate the cropping box and get the cropped part + if fit: + x1 = y1 = 0 + x2, y2 = image.size + wRatio = 1.0 * x2/box[0] + hRatio = 1.0 * y2/box[1] + if hRatio > wRatio: + y1 = y2/2-box[1]*wRatio/2 + y2 = y2/2+box[1]*wRatio/2 + else: + x1 = x2/2-box[0]*hRatio/2 + x2 = x2/2+box[0]*hRatio/2 + image = image.crop((x1,y1,x2,y2)) + + #Resize the image with best quality algorithm ANTI-ALIAS + logger.debug("about to actually downsize using image.thumbnail") + image.thumbnail(box, Image.ANTIALIAS) + logger.debug("it downsized") + +class PicklablePIL: + def __init__(self, image): + self.size = image.size + self.mode = image.mode + self.image_data = image.tostring() + + def get_image(self): + return Image.fromstring(self.mode, self.size, self.image_data) + + def get_pixbuf(self): + return image_to_pixbuf(self.get_image()) + +def get_video_THM_file(fullFileName): + """ + Checks to see if a thumbnail file (THM) is in the same directory as the + file. Expects a full path to be part of the file name. + + Returns the filename, including path, if found, else returns None. + """ + + f = None + name, ext = os.path.splitext(fullFileName) + for e in rpdfile.VIDEO_THUMBNAIL_EXTENSIONS: + if os.path.exists(name + '.' + e): + f = name + '.' + e + break + if os.path.exists(name + '.' + e.upper()): + f = name + '.' + e.upper() + break + + return f + +class Thumbnail: + + # file types from which to remove letterboxing (black bands in the thumbnail + # previews) + crop_thumbnails = ('CR2', 'DNG', 'RAF', 'ORF', 'PEF', 'ARW') + + def _ignore_embedded_160x120_thumbnail(self, max_size_needed, metadata): + return max_size_needed is None or max_size_needed[0] > 160 or max_size_needed[1] > 120 or not metadata.exif_thumbnail.data + + def _get_thumbnail_data(self, metadata, max_size_needed): + logger.debug("Getting thumbnail data %s", max_size_needed) + if self._ignore_embedded_160x120_thumbnail(max_size_needed, metadata): + logger.debug("Ignoring embedded preview") + lowrez = False + previews = metadata.previews + if not previews: + return (None, None) + else: + if max_size_needed: + for thumbnail in previews: + if thumbnail.dimensions[0] >= max_size_needed or thumbnail.dimensions[1] >= max_size_needed: + break + else: + thumbnail = previews[-1] + else: + thumbnail = metadata.exif_thumbnail + lowrez = True + return (thumbnail.data, lowrez) + + def _process_thumbnail(self, image, size_reduced): + if image.mode <> "RGBA": + image = image.convert("RGBA") + + thumbnail = PicklablePIL(image) + if size_reduced is not None: + thumbnail_icon = image.copy() + downsize_pil(thumbnail_icon, size_reduced, fit=False) + thumbnail_icon = PicklablePIL(thumbnail_icon) + else: + thumbnail_icon = None + + return (thumbnail, thumbnail_icon) + + def _get_photo_thumbnail(self, full_file_name, size_max, size_reduced): + thumbnail = None + thumbnail_icon = None + name = os.path.basename(full_file_name) + metadata = pyexiv2.metadata.ImageMetadata(full_file_name) + try: + logger.debug("Read photo metadata...") + metadata.read() + except: + logger.warning("Could not read metadata from %s", full_file_name) + else: + logger.debug("...successfully read photo metadata") + if metadata.mime_type == "image/jpeg" and self._ignore_embedded_160x120_thumbnail(size_max, metadata): + try: + image = Image.open(full_file_name) + lowrez = False + except: + logger.warning("Could not generate thumbnail for jpeg %s ", full_file_name) + image = None + else: + thumbnail_data, lowrez = self._get_thumbnail_data(metadata, max_size_needed=size_max) + logger.debug("_get_thumbnail_data returned") + if not isinstance(thumbnail_data, types.StringType): + image = None + else: + td = cStringIO.StringIO(thumbnail_data) + logger.debug("got td") + try: + image = Image.open(td) + except: + logger.warning("Unreadable thumbnail for %s", full_file_name) + image = None + logger.debug("opened image") + if image: + try: + orientation = metadata['Exif.Image.Orientation'].value + except: + orientation = None + if lowrez: + # need to remove letterboxing / pillarboxing from some + # RAW thumbnails + if os.path.splitext(full_file_name)[1][1:].upper() in Thumbnail.crop_thumbnails: + image2 = image.crop((0, 8, 160, 112)) + image2.load() + image = image2 + if size_max is not None and (image.size[0] > size_max[0] or image.size[1] > size_max[1]): + logger.debug("downsizing") + downsize_pil(image, size_max, fit=False) + logger.debug("downsized") + if orientation == 8: + # rotate counter clockwise + image = image.rotate(90) + elif orientation == 6: + # rotate clockwise + image = image.rotate(270) + elif orientation == 3: + # rotate upside down + image = image.rotate(180) + thumbnail, thumbnail_icon = self._process_thumbnail(image, size_reduced) + + logger.debug("...got thumbnail for %s", full_file_name) + return (thumbnail, thumbnail_icon) + + def _get_video_thumbnail(self, full_file_name, size_max, size_reduced): + thumbnail = None + thumbnail_icon = None + if size_max is None: + size = 0 + else: + size = max(size_max[0], size_max[1]) + image = None + if size > 0 and size <= 160: + thm = get_video_THM_file(full_file_name) + if thm: + try: + thumbnail = gtk.gdk.pixbuf_new_from_file(thm) + except: + logger.warning("Could not open THM file for %s", full_file_name) + thumbnail = add_filmstrip(thumbnail) + image = pixbuf_to_image(thumbnail) + + if image is None: + try: + tmp_dir = tempfile.mkdtemp(prefix="rpd-tmp") + thm = os.path.join(tmp_dir, 'thumbnail.jpg') + subprocess.check_call(['ffmpegthumbnailer', '-i', full_file_name, '-t', '10', '-f', '-o', thm, '-s', str(size)]) + image = Image.open(thm) + image.load() + os.unlink(thm) + os.rmdir(tmp_dir) + except: + image = None + logger.error("Error generating thumbnail for %s", full_file_name) + if image: + thumbnail, thumbnail_icon = self._process_thumbnail(image, size_reduced) + + logger.debug("...got thumbnail for %s", full_file_name) + return (thumbnail, thumbnail_icon) + + def get_thumbnail(self, full_file_name, file_type, size_max=None, size_reduced=None): + logger.debug("Getting thumbnail for %s...", full_file_name) + if file_type == rpdfile.FILE_TYPE_PHOTO: + logger.debug("file type is photo") + return self._get_photo_thumbnail(full_file_name, size_max, size_reduced) + else: + return self._get_video_thumbnail(full_file_name, size_max, size_reduced) + + +class GetPreviewImage(multiprocessing.Process): + def __init__(self, results_pipe): + multiprocessing.Process.__init__(self) + self.daemon = True + self.results_pipe = results_pipe + self.thumbnail_maker = Thumbnail() + self.stock_photo_thumbnail_image = None + self.stock_video_thumbnail_image = None + + def get_stock_image(self, file_type): + """ + Get stock image for file type scaled to the current size of the + """ + if file_type == rpdfile.FILE_TYPE_PHOTO: + if self.stock_photo_thumbnail_image is None: + self.stock_photo_thumbnail_image = PicklablePIL(get_stock_photo_image()) + return self.stock_photo_thumbnail_image + else: + if self.stock_video_thumbnail_image is None: + self.stock_video_thumbnail_image = PicklablePIL(get_stock_video_image()) + return self.stock_video_thumbnail_image + + def run(self): + while True: + unique_id, full_file_name, file_type, size_max = self.results_pipe.recv() + full_size_preview, reduced_size_preview = self.thumbnail_maker.get_thumbnail(full_file_name, file_type, size_max=size_max, size_reduced=(100,100)) + if full_size_preview is None: + full_size_preview = self.get_stock_image(file_type) + self.results_pipe.send((unique_id, full_size_preview, reduced_size_preview)) + + + +class GenerateThumbnails(multiprocessing.Process): + def __init__(self, scan_pid, files, batch_size, results_pipe, terminate_queue, + run_event): + multiprocessing.Process.__init__(self) + self.results_pipe = results_pipe + self.terminate_queue = terminate_queue + self.batch_size = batch_size + self.files = files + self.run_event = run_event + self.results = [] + + self.thumbnail_maker = Thumbnail() + + self.scan_pid = scan_pid + + + def run(self): + counter = 0 + i = 0 + for f in self.files: + + # pause if instructed by the caller + self.run_event.wait() + + if not self.terminate_queue.empty(): + x = self.terminate_queue.get() + # terminate immediately + logger.info("Terminating thumbnailing") + return None + + + thumbnail, thumbnail_icon = self.thumbnail_maker.get_thumbnail( + f.full_file_name, + f.file_type, + (160, 120), (100,100)) + + self.results.append((f.unique_id, thumbnail_icon, thumbnail)) + counter += 1 + if counter == self.batch_size: + self.results_pipe.send((rpdmp.CONN_PARTIAL, self.results)) + self.results = [] + counter = 0 + i += 1 + + if counter > 0: + # send any remaining results + self.results_pipe.send((rpdmp.CONN_PARTIAL, self.results)) + self.results_pipe.send((rpdmp.CONN_COMPLETE, self.scan_pid)) + self.results_pipe.close() + diff --git a/rapid/utilities.py b/rapid/utilities.py new file mode 100644 index 0000000..ad77a29 --- /dev/null +++ b/rapid/utilities.py @@ -0,0 +1,151 @@ +#!/usr/bin/python +# -*- coding: latin1 -*- + +### Copyright (C) 2007 - 2011 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 gio +import gtk +from PIL import Image +import distutils.version + +def get_full_path(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 is_directory(path): + + # for some very strange reason, doing it the GIO way fails with + # unknown type, even for directories! + return os.path.isdir(path) + + if False: + d = gio.File(path) + if d.query_exists(): + file_info = d.query_filesystem_info(attributes="standard::type") + file_type = file_info.get_file_type() + if file_type == gio.FILE_TYPE_DIRECTORY: + return True + + return False + +def format_size_for_user(bytes, zero_string="", with_decimals=True, kb_only=False): + """Format an int containing the number of bytes into a string suitable for + printing out to the user. zero_string 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 kb_only: + value = (bytes / (1024.0 * 1024.0 * 1024.0)) + if with_decimals: + format = "%1.1fGB" + else: + format = "%dGB" + elif bytes > (1 << 20) and not kb_only: + value = (bytes / (1024.0 * 1024.0)) + if with_decimals: + format = "%1.1fMB" + else: + format = "%dMB" + elif bytes > (1 << 10): + value = (bytes / 1024.0) + if with_decimals: + format = "%1.1fKB" + else: + format = "%dKB" + elif bytes > 1: + value = bytes + if with_decimals: + format = "%1.1fB" + else: + format = "%dB" + else: + return zero_string + return format % value + +def register_iconsets(icon_info): + """ + Register icons in the icon set if they're not already used + + From http://faq.pygtk.org/index.py?req=show&file=faq08.012.htp + """ + + icon_factory = gtk.IconFactory() + stock_ids = gtk.stock_list_ids() + for stock_id, file in icon_info: + # only load image files when our stock_id is not present + if stock_id not in stock_ids: + pixbuf = gtk.gdk.pixbuf_new_from_file(file) + iconset = gtk.IconSet(pixbuf) + icon_factory.add(stock_id, iconset) + icon_factory.add_default() + +def escape(s): + """ + Replace special characters by SGML entities. + """ + entities = ("&&", "<<", ">>") + for e in entities: + s = s.replace(e[0], e[1:]) + return s + +def image_to_pixbuf(image): + # convert PIL image to pixbuf + # this one handles transparency, unlike the default example in the pygtk FAQ + # this is also from the pygtk FAQ + IS_RGBA = image.mode=='RGBA' + return gtk.gdk.pixbuf_new_from_data( + image.tostring(), # data + gtk.gdk.COLORSPACE_RGB, # color mode + IS_RGBA, # has alpha + 8, # bits + image.size[0], # width + image.size[1], # height + (IS_RGBA and 4 or 3) * image.size[0] # rowstride + ) + +def pixbuf_to_image(pb): + assert(pb.get_colorspace() == gtk.gdk.COLORSPACE_RGB) + dimensions = pb.get_width(), pb.get_height() + stride = pb.get_rowstride() + pixels = pb.get_pixels() + + mode = pb.get_has_alpha() and "RGBA" or "RGB" + image = Image.frombuffer(mode, dimensions, pixels, + "raw", mode, stride, 1) + + if mode == "RGB": + # convert to having an alpha value, so that the image can + # act as a mask in the drop shadow paste + image = image.convert("RGBA") + + return image + +def pythonify_version(v): + """ makes version number a version number in distutils sense""" + return distutils.version.StrictVersion(v.replace( '~','')) + +def human_readable_version(v): + """ returns a version in human readable form""" + v = v.replace('~a', ' alpha ') + v = v.replace('~b', ' beta ') + v = v.replace('~rc', ' RC ') + return v + @@ -43,21 +43,23 @@ class InstallData(install_data): return data_files -package_data={'rapid': ['glade3/rapid.glade', +package_data={'rapid': ['glade3/about.ui', + 'glade3/photo.svg', + 'glade3/photo66.png', + 'glade3/photo_icon.png', + 'glade3/prefs.ui', + 'glade3/rapid.ui', + 'glade3/errorlog.ui', + 'glade3/media-eject.png', 'glade3/rapid-photo-downloader.svg', - 'glade3/rapid-photo-downloader-download-pending.svg', + 'glade3/rapid-photo-downloader-download-pending.png', 'glade3/rapid-photo-downloader-downloaded-with-error.svg', 'glade3/rapid-photo-downloader-downloaded-with-warning.svg', 'glade3/rapid-photo-downloader-downloaded.svg', 'glade3/rapid-photo-downloader-jobcode.svg', - 'glade3/video.png', - 'glade3/video24.png', - 'glade3/video_small_shadow.png', - 'glade3/video_small.png', - 'glade3/photo.png', - 'glade3/photo_small_shadow.png', - 'glade3/photo_small.png', - 'glade3/photo24.png', + 'glade3/thumbnails_icon.png', + 'glade3/video.svg', + 'glade3/video66.png', 'glade3/zoom-in.png', 'glade3/zoom-out.png', ]} |