summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PKG-INFO14
-rw-r--r--README50
-rw-r--r--data/icons/16x16/apps/rapid-photo-downloader.pngbin0 -> 619 bytes
-rw-r--r--data/icons/22x22/apps/rapid-photo-downloader.pngbin0 -> 996 bytes
-rw-r--r--data/icons/24x24/apps/rapid-photo-downloader.pngbin0 -> 1097 bytes
-rw-r--r--data/icons/48x48/apps/rapid-photo-downloader.pngbin0 -> 2602 bytes
-rw-r--r--data/icons/rapid-photo-downloader.xpm223
-rw-r--r--data/rapid-photo-downloader.desktop11
-rw-r--r--doc/rapid-photo-downloader.pod76
-rw-r--r--po/de.po1409
-rw-r--r--po/en_AU.po1173
-rw-r--r--po/en_GB.po1173
-rw-r--r--po/es.po1432
-rw-r--r--po/fi.po1369
-rw-r--r--po/it.po1407
-rw-r--r--po/pl.po1426
-rw-r--r--po/rapid-photo-downloader.pot1268
-rw-r--r--po/ru.po1378
-rwxr-xr-xrapid-photo-downloader5
-rw-r--r--rapid/AUTHORS1
-rw-r--r--rapid/COPYING339
-rw-r--r--rapid/ChangeLog393
-rw-r--r--rapid/INSTALL36
-rw-r--r--rapid/TODO26
-rw-r--r--rapid/ValidatedEntry.py383
-rw-r--r--rapid/__init__.py1
-rw-r--r--rapid/common.py181
-rw-r--r--rapid/config.py58
-rw-r--r--rapid/glade3/image-missing.svg94
-rw-r--r--rapid/glade3/rapid-photo-downloader-about.pngbin0 -> 8084 bytes
-rw-r--r--rapid/glade3/rapid.glade2716
-rw-r--r--rapid/gnomeglade.py166
-rw-r--r--rapid/higdefaults.py8
-rw-r--r--rapid/idletube.py205
-rwxr-xr-xrapid/media.py180
-rwxr-xr-xrapid/metadata.py387
-rw-r--r--rapid/misc.py45
-rw-r--r--rapid/paths.py40
-rw-r--r--rapid/prefs.py182
-rwxr-xr-xrapid/rapid.py3050
-rw-r--r--rapid/renamesubfolderprefs.py1470
-rw-r--r--rapid/renamesubfolderprefstest.py190
-rw-r--r--rapid/tableplusminus.py284
-rw-r--r--setup.py76
44 files changed, 22925 insertions, 0 deletions
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..d1a0900
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,14 @@
+Metadata-Version: 1.0
+Name: rapid-photo-downloader
+Version: 0.0.10
+Summary: Rapid Photo Downloader for Linux
+Home-page: http://www.damonlynch.net/rapid
+Author: Damon Lynch
+Author-email: damonlynch@gmail.com
+License: GPL
+Description: Rapid Photo Downloader is written by a photographer for
+ professional and amateur photographers. It can download photos
+ from multiple cameras, memory cards and Portable Storage Devices
+ simultaneously. It provides many options for subfolder creation,
+ image renaming and backup.
+Platform: linux
diff --git a/README b/README
new file mode 100644
index 0000000..26531a6
--- /dev/null
+++ b/README
@@ -0,0 +1,50 @@
+Rapid Photo Downloader is written by a photographer for professional and amateur
+photographers. Released under the GNU GPL license, it is designed for use on the
+Linux Desktop. It can download photos from multiple cameras, memory cards, and
+Portable Storage Devices simultaneously. It provides many options for subfolder
+creation, image renaming and backup.
+
+It can download images directly from only from those cameras supported by
+libgphoto2, and only on recent Linux distributions (those that contain gvfs).
+This support is experimental. Some cameras do not work. If you cannot browse the
+camera's contents in a file manager (e.g. Nautilus), the camera download will
+not work until the gvfs support is improved.
+
+If you can put your camera into PTP mode, you may find it works a lot better.
+
+Cameras that do not work when not in PTP mode as at May 2009 include the
+Canon 20D and 300D.
+
+For more information see http://damonlynch.net/rapid
+
+Please report any bug or unexepcted behaviour here:
+
+https://launchpad.net/rapid/+filebug
+
+Furthermore, please feel welcome to contribute anything to help this program
+reach more people: translations, feature suggestions, code, artwork, and
+documentation can always be improved!
+
+Installation
+============
+
+See the INSTALL file in the directory rapid.
+
+Documentation
+=============
+
+See http://damonlynch.net/rapid/documentation
+
+Running the program
+===================
+
+Start the program from its menu entry. If you want additional output from the
+command line, from a terminal run:
+
+rapid-photo-downloader
+
+Known Bugs
+==========
+
+See https://bugs.launchpad.net/rapid/+bugs
+
diff --git a/data/icons/16x16/apps/rapid-photo-downloader.png b/data/icons/16x16/apps/rapid-photo-downloader.png
new file mode 100644
index 0000000..97c7d7c
--- /dev/null
+++ b/data/icons/16x16/apps/rapid-photo-downloader.png
Binary files differ
diff --git a/data/icons/22x22/apps/rapid-photo-downloader.png b/data/icons/22x22/apps/rapid-photo-downloader.png
new file mode 100644
index 0000000..e04e432
--- /dev/null
+++ b/data/icons/22x22/apps/rapid-photo-downloader.png
Binary files differ
diff --git a/data/icons/24x24/apps/rapid-photo-downloader.png b/data/icons/24x24/apps/rapid-photo-downloader.png
new file mode 100644
index 0000000..e6ca472
--- /dev/null
+++ b/data/icons/24x24/apps/rapid-photo-downloader.png
Binary files differ
diff --git a/data/icons/48x48/apps/rapid-photo-downloader.png b/data/icons/48x48/apps/rapid-photo-downloader.png
new file mode 100644
index 0000000..52be8ab
--- /dev/null
+++ b/data/icons/48x48/apps/rapid-photo-downloader.png
Binary files differ
diff --git a/data/icons/rapid-photo-downloader.xpm b/data/icons/rapid-photo-downloader.xpm
new file mode 100644
index 0000000..aad262c
--- /dev/null
+++ b/data/icons/rapid-photo-downloader.xpm
@@ -0,0 +1,223 @@
+/* XPM */
+static char *rapid_photo_downloader[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 185 2",
+" c #6B2F54",
+". c #6F7C47",
+"X c #67764F",
+"o c #747E43",
+"O c #667550",
+"+ c #61745B",
+"@ c #5C4975",
+"# c #405F76",
+"$ c #5C517D",
+"% c #436173",
+"& c #426179",
+"* c #BB0D0D",
+"= c #BB120C",
+"- c #B30E18",
+"; c #BF1411",
+": c #B3141F",
+"> c #B23B01",
+", c #A81D25",
+"< c #B51621",
+"1 c #B61F25",
+"2 c #B51F28",
+"3 c #CC0202",
+"4 c #C90508",
+"5 c #D40101",
+"6 c #D60C0C",
+"7 c #C81818",
+"8 c #D41414",
+"9 c #D81616",
+"0 c #D41A1B",
+"q c #D91F1F",
+"w c #C6212A",
+"e c #CD292F",
+"r c #DA2424",
+"t c #D92E2F",
+"y c #CD2C33",
+"u c #CF3036",
+"i c #D93032",
+"p c #D03439",
+"a c #D1383E",
+"s c #B14300",
+"d c #B24C00",
+"f c #B35A00",
+"g c #BF5A00",
+"h c #B46200",
+"j c #B36A00",
+"k c #B57200",
+"l c #B57C00",
+"z c #C06500",
+"x c #CC6100",
+"c c #C16B00",
+"v c #CE6E00",
+"b c #D96900",
+"n c #C17000",
+"m c #CE7400",
+"M c #C27C00",
+"N c #CF7A00",
+"B c #DB7600",
+"V c #DC7D00",
+"C c #B53D4B",
+"Z c #D23C42",
+"A c #DC3F40",
+"S c #D34247",
+"D c #D44448",
+"F c #D74B4C",
+"G c #D94C4F",
+"H c #D54D50",
+"J c #DB4F51",
+"K c #D65052",
+"L c #79813E",
+"P c #78854C",
+"I c #708056",
+"U c #7C8C5C",
+"Y c #9D951C",
+"T c #B58100",
+"R c #AA9D10",
+"E c #A29918",
+"W c #B4A306",
+"Q c #B0A00B",
+"! c #B3A716",
+"~ c #B7AB11",
+"^ c #878D3E",
+"/ c #8C903A",
+"( c #969A3C",
+") c #A1A53F",
+"_ c #C38300",
+"` c #C48C00",
+"' c #D18600",
+"] c #DE8300",
+"[ c #D28C00",
+"{ c #C59400",
+"} c #D29200",
+"| c #D39B00",
+" . c #E09300",
+".. c #E19D00",
+"X. c #C6A200",
+"o. c #C7A800",
+"O. c #D5A400",
+"+. c #C6B304",
+"@. c #CBB600",
+"#. c #C2B008",
+"$. c #D7B400",
+"%. c #D2BE09",
+"&. c #C1B517",
+"*. c #C7B812",
+"=. c #E3A400",
+"-. c #E4AA00",
+";. c #E5B100",
+":. c #E7BE00",
+">. c #E6883A",
+",. c #E6923A",
+"<. c #E8973B",
+"1. c #E89C3C",
+"2. c #E9A53C",
+"3. c #EAAD3C",
+"4. c #ECB33C",
+"5. c #ECBA3B",
+"6. c #D7C304",
+"7. c #DCC500",
+"8. c #D6C613",
+"9. c #D1C318",
+"0. c #E8C500",
+"q. c #E2CE09",
+"w. c #E7D104",
+"e. c #EDD400",
+"r. c #EEC539",
+"t. c #EFCB39",
+"y. c #828A43",
+"u. c #818E4F",
+"i. c #8B9446",
+"p. c #909741",
+"a. c #959E49",
+"s. c #8A9753",
+"d. c #9CA244",
+"f. c #9FAA7E",
+"g. c #BDBD65",
+"h. c #B9BB68",
+"j. c #C6C35D",
+"k. c #C9C359",
+"l. c #C3C160",
+"z. c #254C83",
+"x. c #284F86",
+"c. c #2E5687",
+"v. c #2D548A",
+"b. c #2D588F",
+"n. c #315786",
+"m. c #325884",
+"M. c #30578E",
+"N. c #2E5A94",
+"B. c #335D94",
+"V. c #385F94",
+"C. c #305E9A",
+"Z. c #356097",
+"A. c #3C6496",
+"S. c #32619D",
+"D. c #39649C",
+"F. c #3D689F",
+"G. c #3364A2",
+"H. c #3B67A0",
+"J. c #3C6AA5",
+"K. c #3D6CA8",
+"L. c #4D5584",
+"P. c #595885",
+"I. c #615781",
+"U. c #625882",
+"Y. c #426DA4",
+"T. c #416EA8",
+"R. c #4770A7",
+"E. c #4470A8",
+"W. c #4B75AA",
+"Q. c #5174A6",
+"!. c #5476A8",
+"~. c #517AAE",
+"^. c #567CB0",
+"/. c #657FAC",
+"(. c #5E82AF",
+"). c #5780B4",
+"_. c #5980B2",
+"`. c #6386B3",
+"'. c #6889B4",
+"]. c #8C9A8A",
+"[. c #93A085",
+"{. c #98A783",
+"}. c #9CA980",
+"|. c #91A288",
+" X c None",
+/* pixels */
+" X X X X X X X X X X X X X Xw w w w w w w w w w w w w X X X X X",
+" X X X X X X X X X X X X XJ 3.3.4.2.5.1.5.<.r.,.t.>.a S X X X X",
+" X X X X X X X X X X X X XF .. .=. .-.] ;.V :.B 0.b 6 q F X X X",
+" X X X X X X X X X X X X XH } [ | ' | N O.m $.v $.x 6 5 9 D X X",
+" X X X X X X X X X X X X XH _ _ ` M { c { c { c o.g 8 5 6 D X X",
+" X X X X X X X X X X X X XH h f h f j d k d l s T > 8 5 5 D X X",
+" X X X X X X X X X X X X XJ ; * = * = * = * = * = 7 6 5 r Z X X",
+" X X X X X X X X X X X X XC < 2 < 6 6 6 6 6 6 6 6 5 5 5 i e X X",
+" X X X(.h.f.g.}.l.{.j.|.k.[.k.].`.@ 3 5 5 5 5 5 5 5 5 5 t y X X",
+" X X X`.9.) 8.d.q.a.w.s.e.s.e.u.J._.P.- 3 3 3 3 3 3 3 3 6 Z X X",
+" X X X`.&.( *.p.6.i.6.u.7.u.7.U J.G.).P.6 5 5 6 6 5 6 3 5 Z X X",
+" X X X`.! / ~ ^ #.y.+.P @.P @.I K.G.T.U.5 5 5 5 5 5 6 3 5 Z X X",
+" X X X'.Y L E o R . Q X W O W + K.G.Y.I.5 5 5 5 5 5 5 3 5 a X X",
+" X X X'.& m.& n.& v.& c.% v.% A.K.C.W.I.5 5 5 5 5 5 5 3 6 a X X",
+" X X X_.T.E.E.E.E.E.E.E.E.E.E.K.G.S.!. 5 5 5 5 5 5 5 3 5 p X X",
+" X X X^.G.G.G.G.G.G.G.G.G.G.S.S.C.G.!. 5 5 5 5 5 5 5 3 5 p X X",
+" X X X^.G.G.C.G.S.S.S.C.C.C.C.C.C.C.W.$ 5 5 5 5 5 5 5 3 5 u X X",
+" X X X^.G.J.J.K.K.K.J.J.J.H.H.J.H.C.H.$ 5 5 5 5 5 5 5 3 5 u X X",
+" X X X^.G.G.G.G.G.G.G.S.S.S.C.S.D.N.F.$ 5 5 5 5 5 5 5 5 5 y X X",
+" X X X~.G.J.G.G.G.G.G.S.S.S.S.C.C.N.D.$ 5 5 5 5 5 5 5 5 5 y X X",
+" X X XW.G.G.G.G.G.G.S.S.S.C.C.C.S.N.D.$ 5 5 5 5 5 5 5 5 5 e X X",
+" X X XW.C.G.G.G.S.S.S.C.C.C.C.C.B.N.Z.$ 6 6 6 6 6 6 9 0 6 y X X",
+" X X XW.C.G.G.S.G.C.S.C.C.N.C.N.N.N.V.L.2 2 2 2 1 1 1 , 1 2 X X",
+" X X XW.C.G.C.G.C.C.C.C.C.C.C.C.N.b.B.V. X X X X X X X X X X X X",
+" X X XR.S.C.S.S.C.C.C.C.C.N.N.N.N.b.V.V. X X X X X X X X X X X X",
+" X X XY.C.S.S.C.C.C.C.N.C.N.N.N.N.b.B.B. X X X X X X X X X X X X",
+" X X XT.C.S.C.C.C.C.C.C.N.N.N.N.b.b.B.M. X X X X X X X X X X X X",
+" X X XY.C.C.C.C.C.N.N.N.N.N.N.N.N.b.B.B. X X X X X X X X X X X X",
+" X X XY.Y.F.S.Z.Z.Z.Z.V.V.B.B.B.V.V.V.M. X X X X X X X X X X X X",
+" X X XM.x.v.M.v.M.v.b.v.v.v.v.v.x.z.v.z. X X X X X X X X X X X X",
+" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X",
+" X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X"
+};
diff --git a/data/rapid-photo-downloader.desktop b/data/rapid-photo-downloader.desktop
new file mode 100644
index 0000000..7d23906
--- /dev/null
+++ b/data/rapid-photo-downloader.desktop
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Version=1.0
+Name=Rapid Photo Downloader
+GenericName=Rapid Photo Downloader
+Comment=Download photos from cameras, memory cards and Portable Storage Devices
+Exec=rapid-photo-downloader
+Icon=rapid-photo-downloader
+MimeType=x-content/image-dcf;
+Terminal=false
+Type=Application
+Categories=Graphics;Photography;
diff --git a/doc/rapid-photo-downloader.pod b/doc/rapid-photo-downloader.pod
new file mode 100644
index 0000000..8720bf5
--- /dev/null
+++ b/doc/rapid-photo-downloader.pod
@@ -0,0 +1,76 @@
+=head1 NAME
+
+rapid-photo-downloader - imports images from cameras, memory cards and other devices
+
+=head1 SYNOPSIS
+
+B<rapid-photo-downloader> [options]
+
+Options:
+ --version
+ -h, --help
+ -v, --verbose
+ -q, --quiet
+ -e, --extensions
+
+=head1 DESCRIPTION
+
+B<Rapid Photo Downloader> downloads photos from cameras, memory cards and Portable
+Storage Devices, providing a variety of options for subfolder creation,
+image renaming and backup. It can download images from more than one device in parallel.
+
+
+=head1 OPTIONS
+
+=item B<--version>
+
+Displays information about the currently installed version and exits.
+
+=item B<-h, --help>
+
+Show help message and exit.
+
+=item B<-v, --verbose>
+
+Displays program information on the command line as the program runs.
+
+=item B<-q, --quiet>
+
+Only display output errors and warnings to the command line as the program runs.
+
+=item B<-e, --extensions>
+
+Displays image file extensions the program recognizes and exits.
+
+=head1 ENVIRONMENT VARIABLES
+
+=item B<LOCALEDIR>
+
+If set, overrides the system-wide directory in which translation data will be searched for.
+
+=head1 BUGS
+
+* Support for downloading directly from cameras is experimental. Not all cameras are supported.
+
+* Closing log window with window manager 'x' instead of 'close' button is not yet supported.
+
+Please report bugs at https://bugs.launchpad.net/rapid
+
+=head1 AUTHORS
+
+B<Rapid Photo Downloader> was written by Damon Lynch <damonlynch@gmail.com>.
+
+This manual page was written by Damon Lynch.
+
+=head1 COPYRIGHT
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+On Debian GNU/Linux systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+=cut
+
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000..2c50971
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,1409 @@
+# German translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: 2009-05-30 08:00+0000\n"
+"Last-Translator: groovy <Unknown>\n"
+"Language-Team: German <de@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-05-30 09:36+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr "Rapid Photo Downloader"
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr "Anzahl der ungültigen Downloads von heute.\n"
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr "Wert wird auf Null zurückgesetzt.\n"
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr "Der Vorgabewert für 'Start des Tages' ist ungültig.\n"
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr "Die Zeit wird auf Mitternacht zurückgesetzt.\n"
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr "Fehler in den Einstellungen zum Umbenennen der Dateien"
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr "Diese Einstellungen enthalten einen Fehler:\n"
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr "Die Einstellungen werden auf die Standardwerte zurückgesetzt."
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr "Fehler in den Download-Unterordner Einstellungen"
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr "Wählen Sie einen Ordner für den Download der Bilder"
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr "Wählen Sie einen Bilder Ordner"
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr ""
+"Wählen Sie einen Ordner zur Speicherung der Sicherungskopien der Bilder"
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+"<i><b>Warnung:</b> Die vorhandenen Metadaten der Bilder sind nicht "
+"vollständig, der neue Name kann nicht erstellt werden. Bitte wählen Sie "
+"andere Einstellungen für die Umbenennung der Bilder</i>"
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+"<i><b>Warnung:</b> Die vorhandenen Metadaten der Bilder sind nicht "
+"vollständig, der gewünschte Ordner kann nicht erstellt werden. Bitte wählen "
+"Sie andere Einstellungen für die Erstellung der Ordner</i>"
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr "<i>Beispiel: %s</i>"
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr ""
+"Es wurden einige unnötige Werte in den Einstellungen für Unterordner "
+"entfernt."
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+"Die gewählten Einstellungen für Unterordner sind ungültig und können nicht "
+"benutzt werden.\n"
+"Sie werden auf Standardwerte zurückgesetzt."
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr "ExternesLaufwerk1"
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr "ExternesLaufwerk2"
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr "Überprüfe Laufwerke ..."
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr "Fehler in den Programmeinstellungen."
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+"\n"
+"Bitte überprüfen Sie die Einstellungen, starten Sie das Programm neu und "
+"versuchen es erneut."
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr "Der Download kann nicht weitergeführt werden"
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr "0 von %s Bildern kopiert"
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+"Überprüfung der Laufwerke abgeschlossen: %(number)s Bilder auf %(device)s "
+"gefunden"
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr ""
+"Überprüfung der Laufwerke abgeschlossen: Keine Bilder gefunden auf %s"
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr "Der Dateiname konnte nicht erzeugt werden"
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Quelle: %(source)s\n"
+"Problem: %(problem)s"
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Der Dateiname konnte nicht erzeugt werden. Bitte überprüfen Sie die "
+"Metadaten der Bilddatei."
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Quelle: %(source)s\n"
+"Ziel: %(destination)s\n"
+"Problem: %(problem)s"
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr "Das Bild konnte nicht geöffnet werden"
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr "Quelle: %s"
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr "Das Bild enthält keine Metadaten"
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+"Die Metadaten sind Voraussetzung für die Erstellung der Unterordner / "
+"Dateinamen\n"
+"Quelle: %s"
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Der Unterordner konnte nicht erzeugt werden. Bitte überprüfen Sie die "
+"Metadaten der Bilddatei."
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Unterordner: %(subfolder)s\n"
+"Bild: %(image)s\n"
+"Problem: %(problem)s"
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+"Quelle: %(source)s\n"
+"Ziel: %(destination)s"
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr "Die eindeutige Bezeichnung '%s' wurde hinzugefügt"
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+"Ein neuer Tag hat begonnen - die Anzahl der 'Downloads Heute' wird "
+"zurückgesetzt"
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr "Fehler beim Kopieren"
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+"Quelle: %(source)s\n"
+"Ziel: %(destination)s\n"
+"Fehler: %(errorno)s %(strerror)s"
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr "Die Datei wurde nicht kopiert."
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr "Die Sicherungskopie besteht bereits"
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr "Fehler beim Erstellen der Sicherungskopie"
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Das Zielverzeichnis konnte nicht erstellt werden\n"
+"%(directory)s\n"
+"Fehler: %(errno)s %(strerror)s"
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Quelle: %(source)s\n"
+"Ziel: %(destination)s\n"
+"Fehler: %(errno)s %(strerror)s"
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr "Das Laufwerk kann nun entfernt werden"
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr "%s Bilder heruntergeladen"
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr "%s Bilder übersprungen"
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr "Warnungen"
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr "Fehler"
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr "Das Laufwerk für die Sicherungskopien fehlt"
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr "Das Laufwerk für die Sicherungskopien konnte nicht gefunden werden."
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr "Das Laufwerk enthält keine Bilddateien."
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr "Der Download von %s hat begonnen"
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr "Bild übersprungen"
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr "Bilddatei überschrieben"
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr "Bilddatei existiert bereits"
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr "Die Datei enthält kein Vorschaubild"
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr "%(number)s von %(total)s Bildern kopiert"
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr "Download von %s abgeschlossen"
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr "Laufwerk"
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr "Grösse"
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr "Fortschritt im Download"
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr "Vorschaubild kann nicht angezeigt werden"
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr "Es könnte defekt sein"
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr "Einige Einstellungen werden zurückgesetzt."
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+"Eine neuere Version des Programms wurde bereits auf diesem Computer "
+"aufgerufen.\n"
+"\n"
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+"Die Voreinstellungen scheinen gültig zu sein, aber bitte überprüfen Sie "
+"diese."
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr ""
+"Einige Voreinstellungen sind ungültig, sie werden auf die Standardwerte "
+"zurückgesetzt."
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr "Warnung:"
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+"Diese Version des Programms ist neuer als bis bisherige. Die "
+"Voreinstellungen werden überprüft."
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr "Die Voreinstellungen wurden geändert."
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+"Diese Version des Programms ist neuer als bis bisherige. Die "
+"Voreinstellungen wurden angepasst\n"
+"Bitte überprüfen Sie diese."
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr "Es mussten keine Voreinstellungen angepasst werden."
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+"Die Version des Programms verwendet andere Voreinstellungen als die "
+"bisherige Version. Einige der bestehenden Einstellungen sind ungültig und "
+"werden auf die Standardwerte zurückgesetzt."
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr "Bei der Verwendung von pynotify ist ein Problem aufgetreten."
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr "Die Werte des pynotify Servers konnten nicht abgefragt werden."
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr "und"
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr "Die Sicherungslaufwerke werden verwendet"
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr "Das Sicherungslaufwerk wird verwendet"
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr "Es wurden keine Sicherungslaufwerke gefunden"
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr "Die %(device)s gefunden auf Pfad %(path)s"
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr "Der automatische Downloadbeginn ist eingeschaltet"
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr "Der automatische Downloadbeginn ist ausgeschaltet"
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr "Verwende den manuell eingegebenen Pfad"
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr "Alle Downloads sind abgeschlossen"
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr "MB/s"
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr "Etwa 1 Sekunde verbleibend"
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr "Etwa %i Sekunden verbleibend"
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr "Etwa 1 Minute verbleibend"
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr "Etwa %(minutes)i:%(seconds)02i Minuten verbleibend"
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr "Bilder heruntergeladen"
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr "Bilder übersprungen"
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr "_Download "
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr "_Pause"
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr "Die Voreinstellungen wurden geändert."
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr "Auf Wiedersehen"
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+"Zeige die Programminformationen an, wenn das Programm aus der Kommandozeile "
+"aufgerufen wurde (Voreinstellung: %default)"
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr "Zeige Fehlermeldungen nur auf der Kommandozeile an"
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr "Anzeigen der gültigen Deteiendungen und beenden"
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr "und %s"
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr "Verwende"
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr "%s wird bereits ausgeführt"
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr "Datum Zeit"
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr "Text"
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr "Dateiname"
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr "Metadaten"
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr "Sequenzen"
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr "Bilddatum"
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr "Heute"
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr "Gestern"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr "Name + Erweiterung"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr "Name"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr "Erweiterung"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr "Bildnummer"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr "Blende"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr "ISO-Wert"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr "Belichtungszeit"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr "Brennweite"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr "Kamerahersteller"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr "Kameramodell"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr "Kameramodell (kurz)"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr "Kameramodell (kurz, Bindestriche)"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr "Seriennummer"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr "Anzahl der Auslösungen"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr "Besitzername"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr "Downloads heute"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr "Sitzungsnummer"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr "Nummer des Unterverzeichnisses"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr "Gespeicherte Nummer"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr "Vorlaufender Buchstabe"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr "Alle Ziffern"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr "Letzte Ziffer"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr "Letzte 2 Ziffern"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr "Letzte 3 Ziffern"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr "Letze 4 Ziffern"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr "Ursprüngliche Schreibweise"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr "Grossschrift"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr "Kleinschrift"
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr "Eine Ziffer"
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr "Zwei Ziffern"
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr "Drei Ziffern"
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr "Vier Ziffern"
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr "Fünf Ziffern"
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr "Sechs Ziffern"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr "Hundertstelsekunden"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr "JJJJMMTT"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr "JJJJ-MM-TT"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr "JJMMTT"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr "JJ-MM-TT"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr "MMTTJJJJ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr "MMTTJJ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr "MMTT"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr "TTMMJJJJ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr "TTMMJJ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr "JJJJ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr "JJ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr "MM"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr "TT"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr "HHMMSS"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr "HHMM"
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+"Voreinstellung '%(key)s' ist ungültig.\n"
+"Erwarteter Wert %(value)s"
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr "Vorgaben für Wert '%(value)s' ist ungültig"
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr "Diese Voreinstellungen sind falsch formatiert:"
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr "Das Bild enthält keine Hunderstelsekunden-Informationen"
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr "%s Metadaten sind im Bild nicht vorhanden"
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr ""
+"Fehler in den Datum/Zeit Informationen. Der Wert %s scheint ungültig zu sein"
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr ""
+"Erweiterung wurde angegeben, aber der Dateiname enthält keine Erweiterung"
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr ""
+"Eine Bildnummer wurde angegeben, aber der Dateiname enthält keine Nummer"
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr "Ein Fehler ist aufgetreten bei der Erstellung des Namens mit %s"
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr "Die Unterordnereinstellungen sollten nicht mit %s beginnen"
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr "Die Unterordnereinstellungen sollten nicht mit %s enden"
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+"Die Unterordnereinstellungen sollten nicht zwei %s nacheinander enthalten"
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr " hh:mm"
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ":"
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr "<b>Datensicherung</b>"
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr "<b>Kompatibilität mit anderen Betriebssystemen</b>"
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr "<b>Download Ordner</b>"
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr "<b>Download Unterverzeichnis</b>"
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr "<b>Beispiel</b>"
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr "<b>Laufwerke mit Bilddaten</b>"
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr "<b>Konfilkte der Bildernamen</b>"
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr "<b>Umbenennung von Bildern</b>"
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr "<b>Fehlende Sicherungslaufwerke</b>"
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr "<b>Programm Automatisierung</b>"
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr "<b>Sequenznummern</b>"
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr "<i>/medium/externeslaufwerk/Fotos</i>"
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr "<i>Beispiel: /home/user/Fotos</i>"
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr "<i>Beispiel:</i>"
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr "<i>Neu:</i>"
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr "<i>Original:</i>"
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Automatisierung</span>"
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Datensicherung</span>\t"
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Download Verzeichnis</span>"
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Fehlerbehandlung</span>"
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Laufwerke</span>"
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Umbenennung von Dateien</span>\t"
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Einstellungen zur Umbenennung</span>"
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr "Füge eine eindeutige Information hinzu"
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr "Suche automatisch nach portablen Laufwerken"
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr "Suche automatisch nach Backuplaufwerken"
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr "Suche automatisch nach Laufwerken mit Bildern"
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr "Automatisierung"
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr "Datensicherung"
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr "Verzeichnis für Datensicherung:"
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr "Ziel der Datensicherung"
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr "Erstelle Sicherung der Bilder beim Herunterladen"
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+"Wählen Sie das Downloadverzeichnis. Unterverzeichnisse werden je nach "
+"gewählten Einstellungen automatisch erzeugt."
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+"Wählen Sie das Bild zu überspringen oder eine eindeutige Bezeichnung "
+"einzufügen"
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr "Copyright Damon Lynch 2007-09"
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr "Beginn des Tages:"
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr "Download / Pause"
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr "Downloadverzeichnis"
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr "Downloadverzeichnis:"
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr "Downloads heute:"
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr "Fehlerbehandlung"
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr "Fehlerprotokoll"
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr "Beende das Programm nach Abschluss des Downloads"
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+"Wählen Sie das genaue Verzeichnis für die Datensicherung, falls die "
+"automatische Erkennung ausgeschaltet ist."
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+"Wählen Sie das genaue Verzeichnis für die Bilder, falls die automatische "
+"Erkennung ausgeschaltet ist."
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+"Wenn Sie die automatische Erkennung für portable Geräte aktivieren, wird das "
+"gesamte Gerät nach Fotos durchsucht. Bei sehr großen Datenträgern kann dies "
+"eine Weile dauern."
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr "Ignoriere"
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr "Laufwerke mit Bildern"
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr "Dateiumbenennung"
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+"Laufwerke mit Bilddaten sind Geräte, von denen Fotos heruntergeladen werden "
+"können, wie Kameras, Speicherkarten oder portable Speichermedien.\n"
+"\n"
+"Sie können Bilder von mehreren Speichermedien gleichzeitig herunterladen.\n"
+"\n"
+"<i>Wenn das direkte Herunterladen von Ihrer Kamera langsam oder überhaupt "
+"nicht funktioniert, versuchen Sie diese in den PTP Modus zu schalten. Sollte "
+"das nicht möglich sein, verwenden Sie bitte einen Kartenleser.</i>"
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr "Bilder Quelle:"
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr "Importieren Sie Ihre Bilder effizient und zuverlässig"
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr "Überschreibe"
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr "Voreinstellungen: Rapid Photo Downloader"
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr "Optionen für die Umbenennung"
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr "Melden Sie eine Warnung"
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr "Melden Sie einen Fehler"
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr "Überspringe"
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr "Überspringe Download"
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+"Geben Sie ein Verzeichnis an, in welchem die Sicherungskopien auf dem "
+"Laufwerk gespeichert werden.\n"
+"<i>Hinweis: Diese Einstellung wird auch verwendet um festzulegen, ob das "
+"Laufwerk für Sicherungskopien verwendet wird oder nicht. Bitte erstellen Sie "
+"auf jedem Laufwerk, welches Sie zur Datensicherung verwenden wollen, einen "
+"Ordner mit diesem Namen.</i>"
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+"Geben Sie die Zeit im 24-Stunden Format an, wann die Sequenznummer in "
+"<i>Downloads heute</i> zurückgesetzt werden soll."
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+"Gegen Sie an was geschehen soll, falls eine Datei oder eine Sicherungskopie "
+"mit demselben Namen bereits existiert."
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr ""
+"Geben Sie an was geschehen soll, falls keine Sicherungslaufwerke vorhanden "
+"sind."
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+"Geben Sie an was geschehen soll, wenn die Verzeichnisse Zeichen enthalten, "
+"welche von anderen Betriebssystemen nicht unterstützt werden."
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr "Beginn des Downloads bei Programmstart"
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr "Beginn des Downloads beim Einfügen von Bilderlaufwerken"
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr "Gespeicherte Nummer"
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr "Entferne nicht kompatible Zeichen"
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr "Aufwerfen des Bildlaufwerks nach Beendigung des Downloads"
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+"Während der Datensicherung können bestehende Bilder auf dem "
+"Sicherungslaufwerk überschrieben oder übersprungen werden."
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+"Sie können Bilder während des Herunterladens an mehrere Orten sichern, z.B. "
+"auf externe Festplatten."
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr "_Heruntergeladene Dateien nicht mehr anzeigen"
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr "_Fehlerprotokoll"
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr "_Online Hilfe ..."
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr "_Hilfe"
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr "_Machen Sie eine Spende"
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr "_Fotos"
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr "_Problemmeldung"
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr "_Vorschaubilder"
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr "_Übersetzung der Applikation"
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr "_Ansicht"
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr "Für die Übersetzung bitte ignorieren"
+
+#~ msgid "Resequence"
+#~ msgstr "Neunummerierung"
+
+#~ msgid ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>"
+#~ msgstr ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>"
+
+#~ msgid "gtk-help"
+#~ msgstr "gtk-help"
diff --git a/po/en_AU.po b/po/en_AU.po
new file mode 100644
index 0000000..388445a
--- /dev/null
+++ b/po/en_AU.po
@@ -0,0 +1,1173 @@
+# English (Australia) translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-19 18:41+0800\n"
+"PO-Revision-Date: 2009-05-19 11:02+0000\n"
+"Last-Translator: Damon Lynch <damonlynch@gmail.com>\n"
+"Language-Team: English (Australia) <en_AU@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-05-19 11:36+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#: rapid/rapid.py:99 rapid/glade3/rapid.glade.h:59
+msgid "Rapid Photo Downloader"
+msgstr ""
+
+#: rapid/rapid.py:399
+msgid "Invalid Downloads Today value.\n"
+msgstr ""
+
+#: rapid/rapid.py:400
+msgid "Resetting value to zero.\n"
+msgstr ""
+
+#: rapid/rapid.py:439
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr ""
+
+#: rapid/rapid.py:440
+msgid "Resetting to midnight.\n"
+msgstr ""
+
+#: rapid/rapid.py:456
+msgid "Error in Image Rename preferences"
+msgstr ""
+
+#: rapid/rapid.py:465 rapid/rapid.py:1127
+msgid "Sorry,these preferences contain an error:\n"
+msgstr ""
+
+#: rapid/rapid.py:476
+msgid "Resetting to default values."
+msgstr ""
+
+#: rapid/rapid.py:587
+msgid "Error in Download Subfolder preferences"
+msgstr ""
+
+#: rapid/rapid.py:704
+msgid "Select a folder to download photos to"
+msgstr ""
+
+#: rapid/rapid.py:751
+msgid "Select an image folder"
+msgstr ""
+
+#: rapid/rapid.py:773
+msgid "Select a folder in which to backup images"
+msgstr ""
+
+#: rapid/rapid.py:861
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+
+#: rapid/rapid.py:882
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+
+#: rapid/rapid.py:884
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr ""
+
+#. this value is used as an example device when automatic backup device detection is enabled
+#: rapid/rapid.py:1057
+msgid "externaldrive1"
+msgstr ""
+
+#. this value is used as an example device when automatic backup device detection is enabled
+#: rapid/rapid.py:1059
+msgid "externaldrive2"
+msgstr ""
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1116
+msgid "scanning..."
+msgstr ""
+
+#: rapid/rapid.py:1223 rapid/rapid.py:1788
+#, python-format
+msgid "0 of %s images copied"
+msgstr ""
+
+#: rapid/rapid.py:1228
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+
+#: rapid/rapid.py:1234
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr ""
+
+#: rapid/rapid.py:1265
+msgid "Image filename could not be generated"
+msgstr ""
+
+#: rapid/rapid.py:1266
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1270
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+
+#: rapid/rapid.py:1271
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1280
+msgid "Could not open image"
+msgstr ""
+
+#: rapid/rapid.py:1281
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: rapid/rapid.py:1290
+msgid "Image has no metadata"
+msgstr ""
+
+#: rapid/rapid.py:1291
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+
+#: rapid/rapid.py:1303
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+
+#: rapid/rapid.py:1304
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1356 rapid/rapid.py:1384 rapid/rapid.py:1403
+#: rapid/rapid.py:1465
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+
+#: rapid/rapid.py:1405
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr ""
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1422
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+
+#: rapid/rapid.py:1427 rapid/rapid.py:1433
+msgid "Download copying error"
+msgstr ""
+
+#: rapid/rapid.py:1428
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+
+#: rapid/rapid.py:1430 rapid/rapid.py:1503
+msgid "The image was not copied."
+msgstr ""
+
+#: rapid/rapid.py:1464
+msgid "Backup image already exists"
+msgstr ""
+
+#: rapid/rapid.py:1492 rapid/rapid.py:1500 rapid/rapid.py:1506
+msgid "Backing up error"
+msgstr ""
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+
+#: rapid/rapid.py:1501 rapid/rapid.py:1507
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+
+#. The device was automatically unmounted
+#: rapid/rapid.py:1520
+msgid "The device can now be safely removed"
+msgstr ""
+
+#: rapid/rapid.py:1524
+#, python-format
+msgid "%s images downloaded"
+msgstr ""
+
+#: rapid/rapid.py:1526
+#, python-format
+msgid "%s images skipped"
+msgstr ""
+
+#: rapid/rapid.py:1532 rapid/rapid.py:2599
+msgid "warnings"
+msgstr ""
+
+#: rapid/rapid.py:1534 rapid/rapid.py:2601
+msgid "errors"
+msgstr ""
+
+#: rapid/rapid.py:1548
+msgid "Download cannot proceed"
+msgstr ""
+
+#: rapid/rapid.py:1548
+msgid ""
+"There is an error in the program preferences.\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+
+#: rapid/rapid.py:1561
+msgid "Backup device missing"
+msgstr ""
+
+#: rapid/rapid.py:1561
+msgid "No backup device was detected."
+msgstr ""
+
+#: rapid/rapid.py:1565
+msgid "This device has no images to download from."
+msgstr ""
+
+#: rapid/rapid.py:1586
+#, python-format
+msgid "Download has started from %s"
+msgstr ""
+
+#: rapid/rapid.py:1623
+msgid "Image skipped"
+msgstr ""
+
+#: rapid/rapid.py:1624
+msgid "Image overwritten"
+msgstr ""
+
+#: rapid/rapid.py:1625
+msgid "Image already exists"
+msgstr ""
+
+#: rapid/rapid.py:1670
+msgid "Image has no thumbnail"
+msgstr ""
+
+#: rapid/rapid.py:1680
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr ""
+
+#: rapid/rapid.py:1696
+#, python-format
+msgid "Download complete from %s"
+msgstr ""
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1772
+msgid "Device"
+msgstr ""
+
+#. Size refers to the total size of images on the device
+#: rapid/rapid.py:1777
+msgid "Size"
+msgstr ""
+
+#: rapid/rapid.py:1780
+msgid "Download Progress"
+msgstr ""
+
+#: rapid/rapid.py:1896 rapid/rapid.py:1902
+msgid "Thumbnail cannot be displayed"
+msgstr ""
+
+#: rapid/rapid.py:1897 rapid/rapid.py:1903
+msgid "It may be corrupted"
+msgstr ""
+
+#: rapid/rapid.py:2150
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+
+#: rapid/rapid.py:2152
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+
+#: rapid/rapid.py:2154
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2155
+msgid "Warning:"
+msgstr ""
+
+#: rapid/rapid.py:2160
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+
+#: rapid/rapid.py:2167
+msgid "Preferences were modified."
+msgstr ""
+
+#: rapid/rapid.py:2168
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+
+#: rapid/rapid.py:2172
+msgid "No preferences needed to be changed."
+msgstr ""
+
+#: rapid/rapid.py:2174
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2182
+msgid "Problem using pynotify."
+msgstr ""
+
+#: rapid/rapid.py:2198
+msgid "Failed to receive pynotify server capabilities."
+msgstr ""
+
+#: rapid/rapid.py:2236
+msgid "and"
+msgstr ""
+
+#: rapid/rapid.py:2241
+msgid "Using backup devices"
+msgstr ""
+
+#: rapid/rapid.py:2243
+msgid "Using backup device"
+msgstr ""
+
+#: rapid/rapid.py:2245
+msgid "No backup devices detected"
+msgstr ""
+
+#: rapid/rapid.py:2380
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr ""
+
+#: rapid/rapid.py:2384
+msgid "Automatically start download is true"
+msgstr ""
+
+#: rapid/rapid.py:2386
+msgid "Automatically start download is false"
+msgstr ""
+
+#: rapid/rapid.py:2434
+msgid "Using manually specified path"
+msgstr ""
+
+#: rapid/rapid.py:2548 rapid/rapid.py:2594
+msgid "All downloads complete"
+msgstr ""
+
+#: rapid/rapid.py:2562
+msgid "MB/s"
+msgstr ""
+
+#: rapid/rapid.py:2572
+msgid "About 1 second remaining"
+msgstr ""
+
+#: rapid/rapid.py:2574
+#, python-format
+msgid "About %i seconds remaining"
+msgstr ""
+
+#: rapid/rapid.py:2576
+msgid "About 1 minute remaining"
+msgstr ""
+
+#: rapid/rapid.py:2578
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr ""
+
+#: rapid/rapid.py:2595
+msgid "images downloaded"
+msgstr ""
+
+#: rapid/rapid.py:2597
+msgid "images skipped"
+msgstr ""
+
+#. note the space at the end of the label, need it to meet HIG! :(
+#: rapid/rapid.py:2685
+msgid "_Download "
+msgstr ""
+
+#. note the space at the end of the label, need it to meet HIG! :(
+#: rapid/rapid.py:2695
+msgid "_Pause"
+msgstr ""
+
+#: rapid/rapid.py:2752
+msgid "Preferences were changed."
+msgstr ""
+
+#: rapid/rapid.py:2883
+msgid "Goodbye"
+msgstr ""
+
+#: rapid/rapid.py:2892
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+
+#: rapid/rapid.py:2893
+msgid "only output errors to the command line"
+msgstr ""
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:2895
+msgid "list image file extensions the program recognizes and exit"
+msgstr "list image file extensions the program recognises and exit"
+
+#: rapid/rapid.py:2908
+#, python-format
+msgid "and %s"
+msgstr ""
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:2913 rapid/rapid.py:2916
+msgid "Using"
+msgstr ""
+
+#. this application is already running
+#: rapid/rapid.py:2930
+#, python-format
+msgid "%s is already running"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:173
+msgid "Date time"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:174
+msgid "Text"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:175
+msgid "Filename"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Metadata"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Sequences"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Image date"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Today"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Yesterday"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Name + extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Name"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:184
+msgid "Image number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:185
+msgid "Aperture"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:186
+msgid "ISO"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:187
+msgid "Exposure time"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:188
+msgid "Focal length"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:189
+msgid "Camera make"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:190
+msgid "Camera model"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:191
+msgid "Short camera model"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:192
+msgid "Hyphenated short camera model"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:193
+msgid "Serial number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:194
+msgid "Shutter count"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:195
+msgid "Owner name"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:196
+msgid "Downloads today"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:197
+msgid "Session number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:198
+msgid "Subfolder number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:199
+msgid "Stored number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:200
+msgid "Sequence letter"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:201
+msgid "All digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:202
+msgid "Last digit"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:203
+msgid "Last 2 digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:204
+msgid "Last 3 digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:205
+msgid "Last 4 digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:206
+msgid "Original Case"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:207
+msgid "UPPERCASE"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:208
+msgid "lowercase"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:209
+msgid "One digit"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:210
+msgid "Two digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:211
+msgid "Three digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:212
+msgid "Four digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:213
+msgid "Five digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:214
+msgid "Six digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:215
+msgid "Subseconds"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:216
+msgid "YYYYMMDD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:217
+msgid "YYYY-MM-DD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:218
+msgid "YYMMDD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:219
+msgid "YY-MM-DD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:220
+msgid "MMDDYYYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:221
+msgid "MMDDYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:222
+msgid "MMDD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:223
+msgid "DDMMYYYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:224
+msgid "DDMMYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:225
+msgid "YYYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:226
+msgid "YY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:227
+msgid "MM"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:228
+msgid "DD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:229
+msgid "HHMMSS"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:230
+msgid "HHMM"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:599
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:606
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:610
+msgid "These preferences are not well formed:"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:710
+msgid "Subsecond metadata not present in image"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:713 rapid/renamesubfolderprefs.py:836
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:728
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:759
+msgid "extension was specified but image name has no extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:763
+msgid "image number was specified but image filename has no number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:948
+#, python-format
+msgid "error generating name with component %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1264
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1266
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1270
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download Folder"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download folder:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Downloads today:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Error Handling"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Log"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Exit program after completion of successful download"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:48
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:49
+msgid "Ignore"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:50
+msgid "Image Devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Image Rename"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:52
+msgid ""
+"Image devices are devices from which to download photos, such as memory "
+"cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:55
+msgid "Image location:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:56
+msgid "Import your images efficiently and reliably"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:57
+msgid "Overwrite"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:58
+msgid "Preferences: Rapid Photo Downloader"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:60
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:65
+msgid "Rename Options"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:66
+msgid "Report a warning"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:67
+msgid "Report an error"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:68
+msgid "Skip"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Skip download"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:70
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:73
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:75
+msgid "Specify what to do when there are no backup devices."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:76
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:77
+msgid "Start downloading at program startup"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:78
+msgid "Start downloading upon image device insertion"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Stored number:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:80
+msgid "Strip incompatible characters"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:82
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:83
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "_Clear Completed Downloads"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "_Error Log"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:86
+msgid "_Get Help Online..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:87
+msgid "_Help"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Make a Donation..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Photos"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Report a Problem..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Thumbnails"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_View"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "translator-credits"
+msgstr ""
+"Launchpad Contributions:\n"
+" Damon Lynch https://launchpad.net/~dlynch3"
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "translators please ignore this"
+msgstr ""
diff --git a/po/en_GB.po b/po/en_GB.po
new file mode 100644
index 0000000..fe586e9
--- /dev/null
+++ b/po/en_GB.po
@@ -0,0 +1,1173 @@
+# English (United Kingdom) translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-19 18:41+0800\n"
+"PO-Revision-Date: 2009-05-19 11:10+0000\n"
+"Last-Translator: Damon Lynch <damonlynch@gmail.com>\n"
+"Language-Team: English (United Kingdom) <en_GB@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-05-19 11:36+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#: rapid/rapid.py:99 rapid/glade3/rapid.glade.h:59
+msgid "Rapid Photo Downloader"
+msgstr ""
+
+#: rapid/rapid.py:399
+msgid "Invalid Downloads Today value.\n"
+msgstr ""
+
+#: rapid/rapid.py:400
+msgid "Resetting value to zero.\n"
+msgstr ""
+
+#: rapid/rapid.py:439
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr ""
+
+#: rapid/rapid.py:440
+msgid "Resetting to midnight.\n"
+msgstr ""
+
+#: rapid/rapid.py:456
+msgid "Error in Image Rename preferences"
+msgstr ""
+
+#: rapid/rapid.py:465 rapid/rapid.py:1127
+msgid "Sorry,these preferences contain an error:\n"
+msgstr ""
+
+#: rapid/rapid.py:476
+msgid "Resetting to default values."
+msgstr ""
+
+#: rapid/rapid.py:587
+msgid "Error in Download Subfolder preferences"
+msgstr ""
+
+#: rapid/rapid.py:704
+msgid "Select a folder to download photos to"
+msgstr ""
+
+#: rapid/rapid.py:751
+msgid "Select an image folder"
+msgstr ""
+
+#: rapid/rapid.py:773
+msgid "Select a folder in which to backup images"
+msgstr ""
+
+#: rapid/rapid.py:861
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+
+#: rapid/rapid.py:882
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+
+#: rapid/rapid.py:884
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr ""
+
+#. this value is used as an example device when automatic backup device detection is enabled
+#: rapid/rapid.py:1057
+msgid "externaldrive1"
+msgstr ""
+
+#. this value is used as an example device when automatic backup device detection is enabled
+#: rapid/rapid.py:1059
+msgid "externaldrive2"
+msgstr ""
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1116
+msgid "scanning..."
+msgstr ""
+
+#: rapid/rapid.py:1223 rapid/rapid.py:1788
+#, python-format
+msgid "0 of %s images copied"
+msgstr ""
+
+#: rapid/rapid.py:1228
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+
+#: rapid/rapid.py:1234
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr ""
+
+#: rapid/rapid.py:1265
+msgid "Image filename could not be generated"
+msgstr ""
+
+#: rapid/rapid.py:1266
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1270
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+
+#: rapid/rapid.py:1271
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1280
+msgid "Could not open image"
+msgstr ""
+
+#: rapid/rapid.py:1281
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: rapid/rapid.py:1290
+msgid "Image has no metadata"
+msgstr ""
+
+#: rapid/rapid.py:1291
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+
+#: rapid/rapid.py:1303
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+
+#: rapid/rapid.py:1304
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1356 rapid/rapid.py:1384 rapid/rapid.py:1403
+#: rapid/rapid.py:1465
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+
+#: rapid/rapid.py:1405
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr ""
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1422
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+
+#: rapid/rapid.py:1427 rapid/rapid.py:1433
+msgid "Download copying error"
+msgstr ""
+
+#: rapid/rapid.py:1428
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+
+#: rapid/rapid.py:1430 rapid/rapid.py:1503
+msgid "The image was not copied."
+msgstr ""
+
+#: rapid/rapid.py:1464
+msgid "Backup image already exists"
+msgstr ""
+
+#: rapid/rapid.py:1492 rapid/rapid.py:1500 rapid/rapid.py:1506
+msgid "Backing up error"
+msgstr ""
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+
+#: rapid/rapid.py:1501 rapid/rapid.py:1507
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+
+#. The device was automatically unmounted
+#: rapid/rapid.py:1520
+msgid "The device can now be safely removed"
+msgstr ""
+
+#: rapid/rapid.py:1524
+#, python-format
+msgid "%s images downloaded"
+msgstr ""
+
+#: rapid/rapid.py:1526
+#, python-format
+msgid "%s images skipped"
+msgstr ""
+
+#: rapid/rapid.py:1532 rapid/rapid.py:2599
+msgid "warnings"
+msgstr ""
+
+#: rapid/rapid.py:1534 rapid/rapid.py:2601
+msgid "errors"
+msgstr ""
+
+#: rapid/rapid.py:1548
+msgid "Download cannot proceed"
+msgstr ""
+
+#: rapid/rapid.py:1548
+msgid ""
+"There is an error in the program preferences.\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+
+#: rapid/rapid.py:1561
+msgid "Backup device missing"
+msgstr ""
+
+#: rapid/rapid.py:1561
+msgid "No backup device was detected."
+msgstr ""
+
+#: rapid/rapid.py:1565
+msgid "This device has no images to download from."
+msgstr ""
+
+#: rapid/rapid.py:1586
+#, python-format
+msgid "Download has started from %s"
+msgstr ""
+
+#: rapid/rapid.py:1623
+msgid "Image skipped"
+msgstr ""
+
+#: rapid/rapid.py:1624
+msgid "Image overwritten"
+msgstr ""
+
+#: rapid/rapid.py:1625
+msgid "Image already exists"
+msgstr ""
+
+#: rapid/rapid.py:1670
+msgid "Image has no thumbnail"
+msgstr ""
+
+#: rapid/rapid.py:1680
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr ""
+
+#: rapid/rapid.py:1696
+#, python-format
+msgid "Download complete from %s"
+msgstr ""
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1772
+msgid "Device"
+msgstr ""
+
+#. Size refers to the total size of images on the device
+#: rapid/rapid.py:1777
+msgid "Size"
+msgstr ""
+
+#: rapid/rapid.py:1780
+msgid "Download Progress"
+msgstr ""
+
+#: rapid/rapid.py:1896 rapid/rapid.py:1902
+msgid "Thumbnail cannot be displayed"
+msgstr ""
+
+#: rapid/rapid.py:1897 rapid/rapid.py:1903
+msgid "It may be corrupted"
+msgstr ""
+
+#: rapid/rapid.py:2150
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+
+#: rapid/rapid.py:2152
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+
+#: rapid/rapid.py:2154
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2155
+msgid "Warning:"
+msgstr ""
+
+#: rapid/rapid.py:2160
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+
+#: rapid/rapid.py:2167
+msgid "Preferences were modified."
+msgstr ""
+
+#: rapid/rapid.py:2168
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+
+#: rapid/rapid.py:2172
+msgid "No preferences needed to be changed."
+msgstr ""
+
+#: rapid/rapid.py:2174
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2182
+msgid "Problem using pynotify."
+msgstr ""
+
+#: rapid/rapid.py:2198
+msgid "Failed to receive pynotify server capabilities."
+msgstr ""
+
+#: rapid/rapid.py:2236
+msgid "and"
+msgstr ""
+
+#: rapid/rapid.py:2241
+msgid "Using backup devices"
+msgstr ""
+
+#: rapid/rapid.py:2243
+msgid "Using backup device"
+msgstr ""
+
+#: rapid/rapid.py:2245
+msgid "No backup devices detected"
+msgstr ""
+
+#: rapid/rapid.py:2380
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr ""
+
+#: rapid/rapid.py:2384
+msgid "Automatically start download is true"
+msgstr ""
+
+#: rapid/rapid.py:2386
+msgid "Automatically start download is false"
+msgstr ""
+
+#: rapid/rapid.py:2434
+msgid "Using manually specified path"
+msgstr ""
+
+#: rapid/rapid.py:2548 rapid/rapid.py:2594
+msgid "All downloads complete"
+msgstr ""
+
+#: rapid/rapid.py:2562
+msgid "MB/s"
+msgstr ""
+
+#: rapid/rapid.py:2572
+msgid "About 1 second remaining"
+msgstr ""
+
+#: rapid/rapid.py:2574
+#, python-format
+msgid "About %i seconds remaining"
+msgstr ""
+
+#: rapid/rapid.py:2576
+msgid "About 1 minute remaining"
+msgstr ""
+
+#: rapid/rapid.py:2578
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr ""
+
+#: rapid/rapid.py:2595
+msgid "images downloaded"
+msgstr ""
+
+#: rapid/rapid.py:2597
+msgid "images skipped"
+msgstr ""
+
+#. note the space at the end of the label, need it to meet HIG! :(
+#: rapid/rapid.py:2685
+msgid "_Download "
+msgstr ""
+
+#. note the space at the end of the label, need it to meet HIG! :(
+#: rapid/rapid.py:2695
+msgid "_Pause"
+msgstr ""
+
+#: rapid/rapid.py:2752
+msgid "Preferences were changed."
+msgstr ""
+
+#: rapid/rapid.py:2883
+msgid "Goodbye"
+msgstr ""
+
+#: rapid/rapid.py:2892
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+
+#: rapid/rapid.py:2893
+msgid "only output errors to the command line"
+msgstr ""
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:2895
+msgid "list image file extensions the program recognizes and exit"
+msgstr "list image file extensions the program recognises and exit"
+
+#: rapid/rapid.py:2908
+#, python-format
+msgid "and %s"
+msgstr ""
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:2913 rapid/rapid.py:2916
+msgid "Using"
+msgstr ""
+
+#. this application is already running
+#: rapid/rapid.py:2930
+#, python-format
+msgid "%s is already running"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:173
+msgid "Date time"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:174
+msgid "Text"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:175
+msgid "Filename"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Metadata"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Sequences"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Image date"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Today"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Yesterday"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Name + extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Name"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:184
+msgid "Image number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:185
+msgid "Aperture"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:186
+msgid "ISO"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:187
+msgid "Exposure time"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:188
+msgid "Focal length"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:189
+msgid "Camera make"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:190
+msgid "Camera model"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:191
+msgid "Short camera model"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:192
+msgid "Hyphenated short camera model"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:193
+msgid "Serial number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:194
+msgid "Shutter count"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:195
+msgid "Owner name"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:196
+msgid "Downloads today"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:197
+msgid "Session number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:198
+msgid "Subfolder number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:199
+msgid "Stored number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:200
+msgid "Sequence letter"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:201
+msgid "All digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:202
+msgid "Last digit"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:203
+msgid "Last 2 digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:204
+msgid "Last 3 digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:205
+msgid "Last 4 digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:206
+msgid "Original Case"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:207
+msgid "UPPERCASE"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:208
+msgid "lowercase"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:209
+msgid "One digit"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:210
+msgid "Two digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:211
+msgid "Three digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:212
+msgid "Four digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:213
+msgid "Five digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:214
+msgid "Six digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:215
+msgid "Subseconds"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:216
+msgid "YYYYMMDD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:217
+msgid "YYYY-MM-DD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:218
+msgid "YYMMDD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:219
+msgid "YY-MM-DD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:220
+msgid "MMDDYYYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:221
+msgid "MMDDYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:222
+msgid "MMDD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:223
+msgid "DDMMYYYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:224
+msgid "DDMMYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:225
+msgid "YYYY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:226
+msgid "YY"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:227
+msgid "MM"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:228
+msgid "DD"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:229
+msgid "HHMMSS"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:230
+msgid "HHMM"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:599
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:606
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:610
+msgid "These preferences are not well formed:"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:710
+msgid "Subsecond metadata not present in image"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:713 rapid/renamesubfolderprefs.py:836
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:728
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:759
+msgid "extension was specified but image name has no extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:763
+msgid "image number was specified but image filename has no number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:948
+#, python-format
+msgid "error generating name with component %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1264
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1266
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1270
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download Folder"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download folder:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Downloads today:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Error Handling"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Log"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Exit program after completion of successful download"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:48
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:49
+msgid "Ignore"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:50
+msgid "Image Devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Image Rename"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:52
+msgid ""
+"Image devices are devices from which to download photos, such as memory "
+"cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:55
+msgid "Image location:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:56
+msgid "Import your images efficiently and reliably"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:57
+msgid "Overwrite"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:58
+msgid "Preferences: Rapid Photo Downloader"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:60
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:65
+msgid "Rename Options"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:66
+msgid "Report a warning"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:67
+msgid "Report an error"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:68
+msgid "Skip"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Skip download"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:70
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:73
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:75
+msgid "Specify what to do when there are no backup devices."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:76
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:77
+msgid "Start downloading at program startup"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:78
+msgid "Start downloading upon image device insertion"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Stored number:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:80
+msgid "Strip incompatible characters"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:82
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:83
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "_Clear Completed Downloads"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "_Error Log"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:86
+msgid "_Get Help Online..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:87
+msgid "_Help"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Make a Donation..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Photos"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Report a Problem..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Thumbnails"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_View"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "translator-credits"
+msgstr ""
+"Launchpad Contributions:\n"
+" Damon Lynch https://launchpad.net/~dlynch3"
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "translators please ignore this"
+msgstr ""
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..a8b471f
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,1432 @@
+# Spanish translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: 2009-05-30 21:05+0000\n"
+"Last-Translator: Abel O'Rian <abel.orian@gmail.com>\n"
+"Language-Team: Spanish <es@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-05-31 13:32+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr "Rapid Photo Downloader"
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr "Valor inválido de descargas de hoy.\n"
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr "Restablecer valores a cero.\n"
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr "'Inicio de día' valor corrupto.\n"
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr "Restablecer a medianoche.\n"
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr "Error en las preferencias de Renombrar Imagen"
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr "Lo siento, pero estas preferencias contienen un error:\n"
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr "Restablecer a los valores por defecto."
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr "Error en subcarpeta de descargas"
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr "Seleccionar una carpeta para descargar las fotos"
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr "Seleccionar una carpeta de imágenes"
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr "Seleccione una carpeta para respaldar las imágenes"
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+"<i><b>Aviso:</b> No hay suficientes metadatos para poder generar el nombre. "
+"Por favor, use las opciones de renombre.</i>"
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+"<i><b>Aviso:</b> No hay suficientes metadatos para poder generar las "
+"subcarpetas. Por favor, use opciones de renombre.</i>"
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr "<i>Ejemplo: %s</i>"
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr ""
+"Las preferencias de subcarpeta tienen algunos valores removidos "
+"innecesariamente."
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+"Las preferencias de subcarpeta ingresadas son inválidas y no pueden ser "
+"usadas.\n"
+"Estas serán restablecidas a los valores por defecto."
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr "dispositivoexterno1"
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr "dispositivoexterno2"
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr "explorando..."
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr "Hay un error en las preferencis del programa."
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+"\n"
+"Por favor revise las preferencia, reinicie el programa, y pruebe de nuevo."
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr "No se puede proceder con la descarga"
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr "0 de %s imagenes copiadas"
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+"Exploración del dispositivo completada: encontradas %(number)s imágenes en "
+"%(device)s"
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr ""
+"Exploración del dispositivo completada: no se han encontrado imágenes en %s"
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr "Archivo de imagen no se ha generado"
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Origen: %(source)s\n"
+"Problema: %(problem)s"
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"El nombre de la imagen no pudo ser generado correctamente. Revise que hayan "
+"suficientes metadatos en la imagen."
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Origen: %(source)s\n"
+"Destino: %(destination)s\n"
+"Problema: %(problem)s"
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr "No se pudo abrir la imagen"
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr "Origen: %s"
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr "La imagen no tiene metadatos"
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+"Metadatos son esenciales para generar subcarpetas/nombres de imagen.\n"
+"Destino: %s"
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"El nombre de la subcarpeta no puede ser generado correctamente. Compruebe "
+"que hay suficiente metadatos en la imagen."
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Subcarpeta: %(subfolder)s\n"
+"Imagen: %(image)s\n"
+"Problema: %(problem)s"
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+"Origen: %(source)s\n"
+"Destino: %(destination)s"
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr "Identificador único '%s' agregado"
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+"Ha empezado un nuevo día - restableciendo los números de secuencia de "
+"'Descargas del día'"
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr "Error al copiar la descarga"
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+"Origen: %(source)s\n"
+"Destino: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr "La imagen no fue copiada."
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr "La copia de seguridad de la imagen ya existe"
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr "Error en copia de seguridad"
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"El directorio de destino no pudo ser creado\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Origen: %(source)s\n"
+"Destino: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr "El dispositivo ya se puede extraer de forma segura"
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr "%s imágenes descargadas"
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr "%s imagenes saltadas"
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr "avisos"
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr "errores"
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr "Dispositivo de respaldo perdido"
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr "No se detectó un dispositivo de respaldo."
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr "El dispositivo no tiene imágenes para descargar."
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr "La descarga empezó desde %s"
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr "Imagen saltada"
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr "Imagen sobreescrita"
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr "La imagen ya existe"
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr "La magen no tiene miniatura"
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr "%(number)s de %(total)s imágenes copiadas"
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr "Descarga completa desde %s"
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr "Dispositivo"
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr "Tamaño"
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr "Progreso de descarga"
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr "Miniatura no puede mostrarse"
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr "Puede estar corrupta"
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr "Algunas preferencias serán restablecidas."
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+"Una versión mas nueva de este programa fue ejecutada antes en este equipo.\n"
+"\n"
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+"Las preferencias del programa parecen ser válidas, pero por favor revise a "
+"fin de garantizar el correcto funcionamiento."
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr "Lo siento, algunas preferencias son invalidas y serán restablecidas"
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr "Aviso:"
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+"Esta versión del programa es más reciente que la versión previamente "
+"ejecutada. Compruebe las preferencias."
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr "Las preferencias fueron modificadas."
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+"Esta versión del programa utiliza preferencias de la antigua versión. Sus "
+"preferencias han sido actualizadas.\n"
+"\n"
+"Por favor, compruebe el correcto funcionamiento."
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr "Ninguna preferencia necesita ser cambiada."
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+"Esta versión del programa utiliza preferencias de la antigua versión. "
+"Algunas de sus preferencias anteriores no eran válidas, y no pueden ser "
+"actualizadas, por lo que serán restablecidas."
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr "Problema usando pynotify."
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr "Fallo al recibir capacidades del servidor pynotify"
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr "y"
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr "Usando dispositivo de copia de seguridad"
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr "Usando dispositivo de copia de seguridad"
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr "Dispositivos de copia de seguridad no detectados"
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr "Detectado %(device)s con ruta %(path)s"
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr "Iniciar automaticamente la descarga está activa"
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr "Iniciar automaticamente la descarga está desactivada"
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr "Usando manualmente la ruta especifica"
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr "Todas las descargas completadas"
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr "MB/s"
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr "Aproximadamente 1 segundo restante"
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr "Aproximadamente %i segundos restantes"
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr "Aproximadamente 1 minuto restante"
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr "Resta cerca de %(minutes)i:%(seconds)02i minutos"
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr "imagenes descargadas"
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr "Imágenes saltadas"
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr "_Descargar "
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr "_Pausar"
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr "Las preferencias fueron cambiadas."
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr "Adiós"
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+"mostrar la información del programa en la línea de comandos de como se "
+"ejecuta el programa (por defecto: %default)"
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr "solo errores de salida en la línea de comando"
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr ""
+"lista de extensiones de archivo de imagen que el programa reconoce y salir"
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr "y %s"
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr "Usando"
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr "%s ya se está ejecutando"
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr "Fecha"
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr "Texto"
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr "Nombre de archivo"
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr "Metadatos"
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr "Secuencias"
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr "Fecha de la imagen"
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr "Hoy"
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr "Ayer"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr "Nombre + extensión"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr "Nombre"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr "Extensión"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr "Número de imagen"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr "Apertura"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr "ISO"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr "Tiempo de exposición"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr "Longitud focal"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr "Marca cámara"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr "Modelo de la camara"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr "Modelo corto de cámara"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr "Modelo de cámara con guión corto"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr "Número de serie"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr "Obturador contador"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr "Nombre propietario"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr "Descargas de hoy"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr "Número de sesión"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr "Número de subcarpeta"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr "Número almacenado"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr "Letra de secuencia"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr "Todos los digitos"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr "Último dígito"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr "Últimos 2 dígitos"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr "Últimos 3 dígitos"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr "Últimos 4 dígitos"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr "Mantener original"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr "MAYÚSCULAS"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr "minúsculas"
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr "Un dígito"
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr "Dos dígitos"
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr "Tres dígitos"
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr "Cuatro dígitos"
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr "Cinco dígitos"
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr "Seis dígitos"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr "Sub-segundos"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr "AAAAMMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr "AAAA-MM-DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr "AAMMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr "AA-MM-DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr "MMDDAAAA"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr "MMDDAA"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr "MMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr "DDMMAAAA"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr "DDMMAA"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr "AAAA"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr "AA"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr "MM"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr "DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr "HHMMSS"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr "HHMM"
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+"Clave preferida '%(key)s' es inválida.\n"
+"Esperado uno de %(value)s"
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr "Valor '%(value)s' es inválido"
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr "Estas preferencias no están bien formadas:"
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr "Metadato de sub-segundos no esta presente en la imagen"
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr "metadato %s no está presente en la imagen"
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr "Error en el campo de fecha. El valor %s parece inválido"
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr ""
+"La extensión fue especificada, pero el nombre de la imagen no tiene extensión"
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr ""
+"Número de imagen fue especificado, pero el nombre de la imagen no lo tiene"
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr "Error generando nombre con componente %s"
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr "Preferencias de subcarpeta no debería empezar con una %s"
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr "Preferencias de subcarpeta no debería terminar con una %s"
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+"Preferencias de subcarpeta no debería contener dos %s uno después que el otro"
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr " hh:mm"
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ":"
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr "<b>Respaldo</b>"
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr "<b>Compatibilidad con otros Sistemas Operativos</b>"
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr "<b>Carpeta de descargas</b>"
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr "<b>Subcarpeta de descargas</b>"
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr "<b>Ejemplo</b>"
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr "<b>Dispositivos de imagen</b>"
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr "<b>Conflictos en nombre de imagen</b>"
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr "<b>Renombrar imagen</b>"
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr "<b>Dispositivo de respaldo perdido</b>"
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr "<b>Automatización de programa</b>"
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr "<b>Número de secuencias</b>"
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr "<i>/media/externaldrive/Imágenes</i>"
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr "<i>Ejemplo: /home/user/photos</i>"
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr "<i>Ejemplo:</i>"
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr "<i>Nuevo:</i>"
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr "<i>Original:</i>"
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Automatización</span>"
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Respaldo</span>\t"
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Carpeta de descargas</span>"
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Manejo de errores</span>"
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Dispositivos de imagen</span>"
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Renombrar imagen</span>\t"
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Opciones de renombre</span>"
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr "Agregar identificador único"
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr "Detectar automáticamente dispositivos de almacenamiento portables"
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr "Detectar automáticamente dispositivos de respaldo"
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr "Detectar automáticamente dispositivos de imagen"
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr "Automatización"
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr "Respaldo"
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr "Nombre de carpeta de respaldo"
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr "Ruta de respaldo:"
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr "Respaldar fotos al descargarlas"
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+"Seleccione una carpeta de descargas. Las subcarpetas para descargar fotos "
+"serán creadas automáticamente en la carpeta usando la estructura "
+"especificada abajo."
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+"Seleccione si desea saltar la descarga de la imagen, o añadir un "
+"identificador único."
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr "Copyright © Damon Lynch 2007-09"
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr "Día de inicio:"
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr "Descargar / Pausar"
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr "Carpeta de descarga"
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr "Carpeta de descarga:"
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr "Descargas de hoy:"
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr "Manejo de errores"
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr "Registro de error"
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr "Salir del programa al completar exitosamente la descarga"
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+"Si desactiva la detección automática, seleccione la ruta exacta de respaldo."
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+"Si desactiva la detección automática, seleccione la ruta exacta de las "
+"imágenes."
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+"Si activa la detección automática de Dispositivos de almacenamiento "
+"portátil, será revisado completamente en busca de imágenes. En dispositivos "
+"grandes, esto puede tomar algún tiempo."
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr "Ignorar"
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr "Dispositivos de imagen"
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr "Renombrar imagen"
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+"Los dispositivos de imagen son aquellos desde los cuales descargará las "
+"fotos, como cámaras, tarjetas de memoria o Dispositivos de almacenamiento "
+"portátil.\n"
+"\n"
+"Puede descargar fotos desde múltiples dispositivos simultaneamente.\n"
+"\n"
+"<i>Si la descarga desde su cámara funciona lento o no funciona, pruebe "
+"configurarla en modo PTP. Si esto no es posible, considere usar un lector de "
+"tarjetas.</i>"
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr "Ruta de imagen:"
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr "Importar sus imágenes de manera eficiente y fiable"
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr "Sobreescribir"
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr "Preferencias: Rapid Photo Downloader"
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+"Rapid Photo Downloader es software libre; puede redistribuirlo y/o "
+"modificarlo bajo los términos de la Licencia Pública General de GNU tal como "
+"la publica la Free Software Foundation; tanto en la versión 2 de la Licencia "
+"como (a su elección) cualquier versión posterior.\n"
+"\n"
+"Rapid Photo Downloader se distribuye con la esperanza de que será útil,pero "
+"SIN NINGUNA GARANTÍA; sin incluso la garantía implicada de MERCANTIBILIDAD o "
+"ADECUACIÓN PARA UN PROPÓSITO PARTICULAR. Vea la Licencia Pública General de "
+"GNU para más detalles.\n"
+"\n"
+"Debería haber recibido una copia de la Licencia pública General de GNU junto "
+"con Rapid Photo Downloader; si no, escriba a la Free Software Foundation, "
+"Inc,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, EE. UU."
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr "Opciones de renombre"
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr "Reportar un aviso"
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr "Reportar un error"
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr "Saltar"
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr "Saltar descarga"
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+"Especificar la carpeta en la que las copias de seguridad se almacenan en el "
+"dispositivo. \n"
+"\n"
+"<i>Nota: esto también se utilizará para determinar si el dispositivo se "
+"utiliza para las copias de seguridad. Para cada dispositivo que desea "
+"utilizar para hacer copias de seguridad se creará una carpeta con este "
+"nombre.</i>"
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+"Especifique la hora en formato de 24 horas en la que el numero de secuencia "
+"de las <i> Descargas de hoy </i>, debe ser restablecido."
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+"Especificar qué hacer cuando una imagen del mismo nombre ya se ha descargado "
+"o respaldado."
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr "Especificar que hacer cuando no hay dispositivos de respaldo."
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+"Especificar si la imagen y los nombres de las carpetas se le han removido "
+"carácteres que no se permite a otros sistemas operativos."
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr "Empezar descargas al iniciar el programa"
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr "Empezar a descargar sobre dispositivo de imagen insertado"
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr "Número almacenado:"
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr "Quitar carácteres incompatibles"
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr ""
+"Desmontar (\"expulsar\") el dispositivo de imagenes una vez completada la "
+"descarga"
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+"Cuando respalde, elegir si desea sobreescribir la imagen en el dispositivo "
+"de seguridad que tiene el mismo nombre, o de saltar su respaldo."
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+"Puede tener respaldos de sus fotos en múltiples locaciones, por ejemplo: "
+"discos duros externos."
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr "_Limpiar descargas completadas"
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr "_Registro de errores"
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr "_Conseguir ayuda online"
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr "_Ayuda"
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr "_Hacer una donación"
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr "_Fotos"
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr "_Informar de un problema"
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr "_Miniaturas"
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr "_Traducir esta aplicación"
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr "_Ver"
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr "traductores por favor ignoren esto"
+
+#~ msgid ""
+#~ "There is an error in the program preferences.\n"
+#~ "Please check preferences, restart the program, and try again."
+#~ msgstr ""
+#~ "Hay un error en las preferencias del programa.\n"
+#~ "Por favor, compruebe las preferencias, reinicie el programa y pruebe de "
+#~ "nuevo."
+
+#~ msgid ""
+#~ "Image devices are devices from which to download photos, such as memory "
+#~ "cards or Portable Storage Devices.\n"
+#~ "\n"
+#~ "You can download photos from multiple image devices simultaneously."
+#~ msgstr ""
+#~ "Dispositivos de imagen a partir de los cuales descargará fotos, tales como "
+#~ "tarjetas de memoria o dispositivos de almacenamiento portátil.\n"
+#~ "\n"
+#~ "Puede descargar fotos de múltiples dispositivos de imagen."
+
+#~ msgid "Resequence"
+#~ msgstr "Resecuencia"
+
+#~ msgid ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>"
+#~ msgstr ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>"
+
+#~ msgid ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>"
+#~ msgstr ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>"
+
+#~ msgid "gtk-help"
+#~ msgstr "Ayuda"
diff --git a/po/fi.po b/po/fi.po
new file mode 100644
index 0000000..d61697d
--- /dev/null
+++ b/po/fi.po
@@ -0,0 +1,1369 @@
+# Finnish translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: 2009-06-01 18:21+0000\n"
+"Last-Translator: Mikko Ruohola <polarfox@polarfox.net>\n"
+"Language-Team: Finnish <fi@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-06-02 06:24+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr "Nopea kuvien lataus"
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr "Virheelliset lataukset tänään\n"
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr "Palautetaan arvo nollaan.\n"
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr "'Päivän alku' asetuksen arvo on virheellinen\n"
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr "Palautuu keskiyöhön.\n"
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr "Virhe kuvan nimeämisasetuksissa"
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr "Anteeksi, näissä asetuksissa on virhe:\n"
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr "Palautetaan oletusarvot."
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr "Virhe Latauskansion asetuksissa"
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr "Valitse kansio johon kuvan ladataan"
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr "Valitse kuvakansio"
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr "Valitse kansio johon tehdään varmuuskopio"
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+"<i><b>Varoitus:</b> Kuvan metatiedoista puuttuu tietoja tiedostonimen "
+"luontiin. Ole hyvä ja käytä muita nimeämis asetuksia.</i>"
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+"<i><b>Varoitus:</b> Kuvan metatiedoista puuttuu tietoja kansiorakenteen "
+"luontiin. Ole hyvä ja käytä muita kansionnimeämis asetuksia.</i>"
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr "<i>Esimerkki: %s</i>"
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr "Alikansioasetuksista poistettiin tarpeettomia arvoja."
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+"Alikansioasetuksien asetukset ovat virheelliset, eikä niitä voida käyttää.\n"
+"Ne palautetaan oletusasetuksiin."
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr "ulkoinenasema1"
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr "ulkoinenasema2"
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr "etsii..."
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr "Ohjelman setuksissa on virhe."
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+"\n"
+"Ole hyvä ja tarkista asetukset, käynnistä ohjelma uudelleen ja koita "
+"uudestaan."
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr "Latausta ei voida jatkaa"
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr "0 kuvaa %s kuvasta kopioitu"
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+"Laite etsintä on valmis: löytyi %(number)s kuvaa %(device)s laitteesta"
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr "Laite etsintä on valmis: kuvia ei löytynyt sijainnista %s"
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr "Kuvan tiedostonimeä ei pystytty luomaan"
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Lähde: %(source)s\n"
+"Ongelma: %(problem)s"
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Kuvan tiedostonimeä ei pystytty luomaan oikein. Tarkista että kuvassa on "
+"riittävästi metatietoja."
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Lähde: %(source)s\n"
+"Kohde: %(destination)s\n"
+"Ongelma: %(problem)s"
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr "Kuvaa ei voitu avata"
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr "Lähde: %s"
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr "Kuvassa ei ole metatietoja"
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+"Metatieto on välttämätöntä kansiorakenteen ja tiedostonimien luontiin.\n"
+"Lähde: %s"
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Kansiorakennetta ei voitu luoda. Tarkista että kuvassa on riittävästi "
+"metatietoja."
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Alikansio: %(subfolder)s\n"
+"Kuva: %(image)s\n"
+"Ongelma: %(problem)s"
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+"Lähde: %(source)s\n"
+"Kohde: %(destination)s"
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr "Yksilöinti '%s' lisätty"
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr "Uusi päivä on alkanut - Palautetaan 'Latauksia Tänään' luku"
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr "Kopiointivirhe"
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+"Lähde: %(source)s\n"
+"Kohde: %(destination)s\n"
+"Virhe: %(errorno)s %(strerror)s"
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr "Kuvaa ei kopioitu."
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr "Kuvan varmuuskopio on jo olemassa"
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr "Varmuuskopiointi virhe"
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Kohdekansiota ei voitu luoda\n"
+"%(directory)s\n"
+"Virhe: %(errno)s %(strerror)s"
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Lähde: %(source)s\n"
+"Kohde: %(destination)s\n"
+"Virhe: %(errno)s %(strerror)s"
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr "Laite voidaan turvallisesti poistaa"
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr "%s kuvaa ladattu"
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr "%s kuvaa ohitettu"
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr "varoitukset"
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr "virheet"
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr "Varmuuskopiolaite puuttuu"
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr "Varmuuskopiolaitetta ei löytynyt"
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr "Laitteessa ei ole kuvia ladattavaksi."
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr "Lataus lähteestä %s on alkanut"
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr "Kuva ohitettu"
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr "Kuva korvattu"
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr "Kuva on jo olemassa"
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr "Kuvalla ei ole näytekuvaa"
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr "%(number)s kuvaa %(total)s kuvasta kopioitu"
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr "Lataus lähteestä %s valmis"
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr "Laite"
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr "Koko"
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr "Latauksen edistyminen"
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr "Näytekuvaa ei voida näyttää"
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr "Se voi olla vahingoittunut"
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr "Jotkin asetukset palautetaan."
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+"Ohjelman uudempaa versiota on käytetty tässä tietokoneessa.\n"
+"\n"
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+"Ohjelma on kelpaava, mutta ole hyvä ja tarkista että ohjelma toimii oikein."
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr ""
+"Anteeksi, jotkin asetukset ovat virheellisiä ja ne palautetaan "
+"oletusarvoihin."
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr "Varoitus:"
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+"Tämä ohjelma on uudempi kuin aikaisemmin käytetty. Tarkista asetukset."
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr "Asetuksia on muokattu."
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+"Tämä ohjelmaversio käyttää eri asetuksia kuin vanha versio. Asetuksesi on "
+"päivitettu.\n"
+"\n"
+"Ole hyvä ja tarkista ne varmistaaksesi ohjelman toiminta."
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr "Asetuksia ei tarvinnut muuttaa."
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+"Tämä ohjelmaversio käyttää eri asetuksia kuin vanha versio. Jotkin entisistä "
+"asetuksistasi olivat virheellisiä ja niitä ei voitu päivittää. Ne "
+"palautetaan oletuksiin."
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr "Ongelmia pynotifyn käytössä."
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr "Ei saanut pynotify-palvelimen ominaisuuksia."
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr "ja"
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr "Käyttää varmuuskopiolaitteita"
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr "Käyttää varmuuskopiolaitetta"
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr "Varmuuskopiolaitetta ei löytynyt"
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr "Löytyi %(device)s laitetta polusta %(path)s"
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr "Automaattinen latauksen aloitus on päällä"
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr "Automaattinen latauksen aloitus on pois päältä"
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr "Käytetään käsin valittua polkua"
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr "Kaikki lataukset valmiita"
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr "Mt/s"
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr "Noin 1 sekunti jäljellä"
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr "Noin %i sekuntia jäljellä"
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr "Noin 1 minuutti jäljellä"
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr "Noin %(minutes)i:%(seconds)02i minuuttia jäljellä"
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr "kuvia ladattu"
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr "kuvia ohitettu"
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr "_Lataa "
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr "_Keskeytä"
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr "Asetuksia muutettiin."
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr "Näkemiin"
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+"näytä ohjelman tiedot komentorivillä kun ohjelma käynnistetään (oletus: "
+"%default)"
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr "tulosta vain virheet komentoriville"
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr "Listaa kuvatiedostopäätteet jotka ohjelma tunnistaa ja poistu"
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr "ja %s"
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr "Käyttäen"
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr "%s on jo käynnissä"
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr "Ajankohta"
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr "Teksti"
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr "Tiedostonimi"
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr "Metatieto"
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr "Numeroinnit"
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr "Kuvan päivämäärä"
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr "Tänään"
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr "Huomenna"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr "Nimi + pääte"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr "Nimi"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr "Tiedostopääte"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr "Kuvan numero"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr "Aukko"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr "Herkkyys"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr "Valotusaika"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr "Polttoväli"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr "Kameran merkki"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr "Kameran malli"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr "Lyhyt kameramalli"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr "Tavutettu lyhyt kameran malli"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr "Sarjanumero"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr "Suljinlaskuri"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr "Omistajan nimi"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr "Latauksia tänään"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr "Istuntonumero"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr "Alikansion numero"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr "Tallennettu numero"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr "Kirjainsarja"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr "Kaikki numerot"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr "Viimeinen numero"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr "Kaksi viimeistä numeroa"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr "Kolme viimeistä numeroa"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr "Neljä viimeistä numeroa"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr "Alkuperäinen kirjoitusasu"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr "ISOT KIRJAIMET"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr "pienet kirjaimet"
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr "Yksi numero"
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr "Kaksi numeroa"
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr "Kolme numeroa"
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr "Neljä numeroa"
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr "Viisi numeroa"
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr "Kuusi numeroa"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr "sekunnin osat"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr "VVVVKKPP"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr "VVVV-KK-PP"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr "VVKKPP"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr "VV-KK-PP"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr "KKPPVVVV"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr "KKPPVV"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr "KKPP"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr "PPKKVVVV"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr "PPKKVV"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr "VVVV"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr "VV"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr "KK"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr "PP"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr "hhmmss"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr "hhmm"
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+"Asetus '%(key)s' on virheellinen.\n"
+"Tulisi olla yksi näistä %(value)s"
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr "Asetuksen arvo '%(value)s' on virheellinen"
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr "Nämä asetukset eivät ole oikeassa muodossa:"
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr "sekunnin osia ei löydy metatiedoista tässä kuvassa"
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr "%s metatietoa ei löydy tästä kuvasta"
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr "Virhe aikamäärityksessä. Arvo %s näyttää virheelliseltä"
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr ""
+"tiedostopääte oli määritelty mutta kuvan nimessä ei ole tiedostopäätettä"
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr "kuvan numero oli määritelty, mutta tiedostonimessä ei ole numeroa"
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr "virhe luotaessa nimeä osalla %s"
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr "Alikansioiiden asetusten ei tulisi alkaa %s"
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr "Alikansioiden asetusten ei tulisi loppua %s"
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr "Alikansioiden asetusten ei tulisi sisältää kahta vierekkäistä %s"
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr " hh:mm"
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ":"
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr "<b>Varmuuskopio</b>"
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr "<b>Yhteensopivuus käyttöjärjestelmien kanssa</b>"
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr "<b>Latauskansio</b>"
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr "<b>Latausalikansio</b>"
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr "<b>Esimerkki</b>"
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr "<b>Kuva laitteet</b>"
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr "<b>Kuvannimien konfliktit</b>"
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr "<b>Kuvan uudelleennimeäminen</b>"
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr "<b>Puuttuvat varmusskopiolaitteet</b>"
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr "<b>Ohjelman automatiikka</b>"
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr "<b>Numerointi</b>"
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr "<i>/media/ulkoinenlevy/Kuvat</i>"
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr "<i>Esimerkki: /home/käyttäjä/kuvat</i>"
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr "<i>Esimerkki</i>"
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr "<i>Uusi:</i>"
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr "<i>Alkuperäinen:</i>"
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Automatisointi</span>"
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Varmuuskopio</span>\t"
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Latauskansio</span>"
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Virheenkäsittely</span>"
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Kuvalaitteet</span>"
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Kuvan uudelleennimeäminen</span>\t"
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Uudelleennimeämis valinnat</span>"
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr "Lisää yksilöllinen tunniste"
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr "Tunnista automaattisesti ulkoiset tallennuslaitteet"
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr "Tunnista automaattisesti varmuuskopiolaitteet"
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr "Tunnista automaattisesti kuvalaitteet"
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr "Automatisointi"
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr "Varmuuskopio"
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr "Varmuuskopiokansion nimi:"
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr "Varmuuskopioiden sijainti:"
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr "Tee varmuuskopio ladattaessa kuvia"
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+"Valitse latauskansio. Alikansiot ladatuille kuville tehdään automaattisesti "
+"tähän kansioon käyttäen alla määriteltyä rakennetta käyttäen."
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+"Valitse ohitetaanko kuva ladattaessa vai lisätäänkö nimeen yksilöllinen "
+"tunniste."
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr "Tekijänoikeus Damon Lynch 2007-09"
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr "Päivän alku:"
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr "Lataa / Keskeytä"
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr "Latauskansio"
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr "Latauskansio:"
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr "Latauksia tänään:"
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr "Virheenkäsittely"
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr "Virheloki"
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr "Poistu ohjelmasta onnistuneen latauksen jälkeen"
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+"Jos poistat automaattisen tunnistuksen käytöstä, määritä varmuuskopioiden "
+"tarkka sijainti."
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+"Jos poistat automaattisen tunnistuksen käytöstä, määritä tarkka kuvien "
+"sijainti."
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+"Jos kytket päälle automaattisen kannettavan laitteen tunnistuksen, koko "
+"laite käydään läpi kuvia etsittäessä, tämä voi kestää hetken."
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr "Ohita"
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr "Kuvalaitteet"
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr "Kuvan uudelleennimeäminen"
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+"Kuvalaitteet ovat laitteita joista kuvat ladataan, kuten kameroita, "
+"muistikortteja tai muita kannettavia laitteita.\n"
+"\n"
+"Voit ladata valokuvia monesta kuvalaitteesta yhtäaikaa.\n"
+"\n"
+"<i>Jos lataus suoraan kamerasta toimii huonosti tai ei ollenkaan, koita "
+"asettaa se PTP tilaan. Jos ei ole mahdollista, harkitse kortinlukijan "
+"käyttämistä.</i>"
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr "Kuvan sijainti:"
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr "Tuo kuvasti tehokkaasti ja turvallisesti"
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr "Ylikirjoita"
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr "Asetukset: Nopea Valokuvien Lataaja"
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr "Uudelleennimeämis valinnat"
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr "Raportoi varoitus"
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr "Raportoi virhe"
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr "Ohita"
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr "Ohita lataus"
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+"Määritä kansio johon varmuuskopiot tallennetaan laitteessa. \n"
+"\n"
+"<i>Huomaa: tämä määrittää myös käytetäänkö laitetta varmuuskopiointiin vai "
+"ei. Jokaiseen varmuuskopiolaitteeseen tulee tehdä tämän niminen "
+"hakemisto.</i>"
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+"Valitse aika 24 tunnin muodossa jossa <i>Latauksia tänään</i> numerointi "
+"tulisi palauttaa."
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+"Valitse mitä tehdään kun samanniminen kuva on jo ladattu tai varmuuskopioitu."
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr "Valitse mitä tehdään jos varmuuskopiolaitteita ei löydy."
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+"Valitse tuleeko kuva ja hakemistonimistä poistaa merkit joita ei tueta "
+"toisissa käyttöjärjestelmissä."
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr "Aloita lataus kun ohjelma käynnistetään"
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr "Aloita lataus kun kuvalaite kytketään"
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr "Tallennettu numero:"
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr "Poista yhteensopimattomat merkit"
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr "Poista kuvalaite kun lataus on valmis"
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+"Varmuuskopioitaessa, valitse ylikirjoitetaanko kuva varmuuskopiolaitteessa "
+"jos saman niminen kuva on jo olemassa, vai ohitetaanko se."
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+"Voit varmuuskopioida kuvasi useaan kohteeseen kun kuvia ladataan, esim. "
+"ulkoisille kovalevyille."
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr "_Tyhjennä valmistuneet lataukset"
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr "Virheloki"
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr "_Hae ohjeita netistä..."
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr "_Ohje"
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr "_Tee lahjoitus"
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr "_Valokuvat"
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr "_Raportoi ongelma..."
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr "_Näytekuvat"
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr "_Käännä tämä ohjelma..."
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr "_Näytä"
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr "kääntäjät, olkaa hyvä ja olkaa välittämättä tästä"
diff --git a/po/it.po b/po/it.po
new file mode 100644
index 0000000..99a33f1
--- /dev/null
+++ b/po/it.po
@@ -0,0 +1,1407 @@
+# Italian translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: 2009-05-30 08:13+0000\n"
+"Last-Translator: Marco Solari <marcosolari@gmail.com>\n"
+"Language-Team: Italian <it@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-05-30 09:36+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr "Rapid Photo Downloader"
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr "Il valore Downloads Oggi non è valido.\n"
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr "Resetta i valori a zero.\n"
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr "Il valore della preferenza 'Inizio del giorno' è corrotto.\n"
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr "Si resetta a mezzanotte.\n"
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr "Errore nelle preferenze Rinomina Immagine"
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr "Scusa ma queste preferenze contengono un errore:\n"
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr "Si resettano ai valori di default."
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr "Errore nelle preferenze Sottocartella di Download"
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr "Scegliere la cartella in cui scaricare le foto"
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr "Selezionare una cartella contenente le foto"
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr "Selezionare una cartella per le immagini di backup"
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+"<i><b>Attenzione:</b> Non ci sono metadati sufficienti per generare "
+"interamente il nome. Usa diverse opzioni di rinomina.</i>"
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+"<i><b>Attenzione:</b> Non ci sono metadati sufficienti per generare "
+"interamente le sottocartelle. Usa diverse opzioni di nomina delle "
+"sottocartelle.</i>"
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr "<i>Esempio: %s</i>"
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr ""
+"Sono stati rimossi alcuni valori non necessari nelle preferenze "
+"sottocartella."
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+"Le preferenze sottocartella inserite non sono valide e non possono essere "
+"usate.\n"
+"Saranno reimpostate ai loro valori di default."
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr "driveesterno1"
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr "driveesterno1"
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr "scansione in corso..."
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr "C'è un errore nelle referenze programma."
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+"\n"
+"Per favore controlla le preferenze, riavvia il programma e prova di nuovo"
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr "Il download non può procedere"
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr "0 di %s immagini copiate"
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+"Scansione del dispositivo completata: trovate %(number)s immagini in "
+"%(device)s"
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr "Scansione del dispositivo completata: nessuna immagine trovata in %s"
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr "Non si è potuto generare il nome file dell'immagine"
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Origine: %(source)s\n"
+"Problema: %(problem)s"
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Non si è potuto generare correttamente il nome file dell'immagine. "
+"Controllare che ci siano sufficienti metadati per l'immagine."
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Origine: %(source)s\n"
+"Destinazione: %(destination)s\n"
+"Problema: %(problem)s"
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr "Impossibile aprire l'immagine"
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr "Origine: %s"
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr "L'immagine non ha metadati"
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+"I metadati sono essenziali per generare i nomi delle sottocartelle / "
+"immagini.\n"
+"Origine: %s"
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Impossibile generare correttamente il nome della sottocartella. Controllare "
+"che ci siano metadati sufficienti per l'immagine."
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Sottocartella: %(subfolder)s\n"
+"Immagine: %(image)s\n"
+"Problema: %(problem)s"
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+"Origine: %(source)s\n"
+"Destinazione: %(destination)s"
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr "Aggiunto identificatore univoco '%s'"
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+"Un nuovo giorno è iniziato - si resetta il numero di sequenza 'Downloads "
+"Oggi'"
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr "Errore nella copia del download"
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+"Origine: %(source)s\n"
+"Destinazione: %(destination)s\n"
+"Errore: %(errorno)s %(strerror)s"
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr "L'immagine non è stata copiata."
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr "L'immagine di backup esiste già"
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr "Errore durante il backup"
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Non si è potuto creare la cartella di destinazione\n"
+"%(directory)s\n"
+"Errore: %(errno)s %(strerror)s"
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Origine: %(source)s\n"
+"Destinazione: %(destination)s\n"
+"Errore: %(errno)s %(strerror)s"
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr "Il dispositivo può adesso essere rimosso in modo sicuro"
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr "%s immagini scaricate"
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr "%s immagini ignorate"
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr "avvertenze"
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr "errori"
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr "Manca il dispositivo di backup"
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr "Nessun dispositivo di backup è stato rilevato."
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr "Questo dispositivo non ha immagini da scaricare."
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr "Il download è inziato da %s"
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr "Immagine ignorata"
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr "Immagine sovrascritta"
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr "L'immagine esiste già"
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr "L'immagine non ha miniatura"
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr "%(number)s di %(total)s immagini copiate"
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr "Download completato da %s"
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr "Dispositivo"
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr "Dimensione"
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr "Avanzamento del download"
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr "La miniatura non può essere visualizzata"
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr "Può essere corrotto"
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr "Alcune preferenze saranno azzerate."
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+"Una versione più recente di questo programma è stato eseguito su questo "
+"computer.\n"
+"\n"
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+"Le preferenze del programma sembrano essere valide, ma occorre controllarle "
+"per assicurare la correttezza delle operazioni."
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr "Spiacente, alcune preferenze non sono valide e saranno ripristinate."
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr "Attenzione:"
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+"Questa versione del programma è più recente della versione eseguita in "
+"precedenza. Si controllano le preferenze."
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr "Le preferenze sono state modificate."
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+"Questa versione del programma utilizza preferenze diverse dalla vecchia "
+"versione. Le tue preferenze sono state aggiornate.\n"
+"\n"
+"Controllarle per assicurare la correttezza delle operazioni."
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr "Non occorre cambiare alcuna preferenza."
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+"Questa versione del programma utilizza preferenze diverse dalla vecchia "
+"versione. Alcune delle preferenze precedenti non erano valide, e non hanno "
+"potuto essere aggiornate. Saranno reimpostate."
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr "Riscontrato un problema usando pynotify."
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr "Impossibile acquisire le proprietà server di pynotify."
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr "e"
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr "Si utilizzano dispositivi di backup"
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr "Si utilizza un dispositivo di backup"
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr "Non è stato rilevato nessun dispositivo di backup"
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr "Rilevato %(device)s con il percorso %(path)s"
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr "Avvio automatico dei download attivo"
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr "Avvio automatico dei download disattivo"
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr "Si utilizza un percorso specificato manualmente"
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr "Tutti i download completati"
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr "MB/s"
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr "Circa 1 secondo rimanente"
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr "Circa %i secondi rimanenti"
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr "Manca circa 1 minuto"
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr "Circa %(minutes)i:%(seconds)02i minuti rimanenti"
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr "immagini scaricate"
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr "immagini saltate"
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr "_Download "
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr "_Pausa"
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr "Le preferenze sono state modificate."
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr "Arrivederci"
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+"visualizza informazioni sul programma sulla riga comando quando il programma "
+"è in esecuzione (default: %default)"
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr "visualizza solo gli errori sulla riga comando"
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr ""
+"elenca le estensioni per i files delle immagini che il programma riconosce, "
+"ed esce"
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr "e %s"
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr "Si usa"
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr "%s è già in esecuzione"
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr "Data e ora"
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr "Testo"
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr "Nome file"
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr "Metadati"
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr "Ordinamenti"
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr "Data dell'immagine"
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr "Oggi"
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr "Ieri"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr "Nome + estensione"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr "Nome"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr "Estensione"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr "Numero immagine"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr "Apertura"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr "ISO"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr "Tempo di esposizione"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr "Lunghezza focale"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr "Marca della fotocamera"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr "Modello della fotocamera (es.: Canon EOS-1Ds Mark III)"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr "Modello brevissimo della fotocamera (es.: D300)"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr "Modello breve della fotocamera (es.: DSC-P92)"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr "Numero seriale"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr "Contatore dell'otturatore"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr "Nome del proprietario"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr "Downloads oggi"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr "Numero della sessione"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr "Numero della sottocartella"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr "Numero memorizzato"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr "Lettera di sequenza"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr "Tutte le cifre"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr "Ultima cifra"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr "Ultime 2 cifre"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr "Ultime 3 cifre"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr "Ultime 4 cifre"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr "Caso originale"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr "MAIUSCOLO"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr "minuscolo"
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr "Una cifra"
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr "Due cifre"
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr "Tre cifre"
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr "Quattro cifre"
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr "Cinque cifre"
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr "Sei cifre"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr "Sotto-secondi"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr "YYYYMMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr "YYYY-MM-DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr "YYMMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr "YY-MM-DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr "MMDDYYYY"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr "MMDDYY"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr "MMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr "DDMMYYYY"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr "DDMMYY"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr "YYYY"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr "YY"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr "MM"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr "DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr "HHMMSS"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr "HHMM"
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+"La chiave delle preferenze '%(key)s' non è valida\n"
+"Sono previsti uno di %(value)s"
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr "Il valore delle preferenze '%(value)s' non è valido"
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr "Queste preferenze non sono formalmente corrette:"
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr "Metadato sotto-secondi non presente nell'immagine"
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr "Metadato %s non presente nell'immagine"
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr "Errore nel componente data e ora. Il valore %s non sembra valido"
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr ""
+"è stata specificata un'estensione ma il nome dell'immagine non ha estensione"
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr ""
+"è stato specificato un numero immagine ma il nome file dell'immagine non ha "
+"numero"
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr "errore nella generazione del nme con il componente %s"
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr "Le preferenze sottocartella non dovrebbero iniziare con un %s"
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr "Le preferenze sottocartella non dovrebbero terminare con un %s"
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+"Le preferenze sottocartella non dovrebbero contenere due %s uno dopo l'altro"
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr " hh:mm"
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ":"
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr "<b>Backup</b>"
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr "<b>Compatibilità con Altri Sistemi Operativi</b>"
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr "<b>Cartella di Download</b>"
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr "<b>Sottocartella di Download</b>"
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr "<b>Esempio</b>"
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr "<b>Dispositivi Immagine</b>"
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr "<b>Conflitti sul Nome Immagine</b>"
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr "<b>Rinomina Immagine</b>"
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr "<b>Dispositivi di Backup Mancanti</b>"
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr "<b>Automazione Programma</b>"
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr "<b>Numeri di Sequenza</b>"
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr "<i>/media/externaldrive/Photos</i>"
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr "<i>Esempio: /home/utente/fotografie</i>"
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr "<i>Esempio:</i>"
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr "<i>Nuovo:</i>"
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr "<i>Originale:</i>"
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Automazione</span>"
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Cartella di Download</span>"
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Gestione Errori</span>"
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Dispositivi Immagine</span>"
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Rinomina Immagine</span>\t"
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Opzioni di Rinomina</span>"
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr "Aggiunta di un identificatore univoco"
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr "Rileva automaticamente i Dispositivi di Memorizzazione Portatile"
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr "Rileva automaticamente i dispositivi di backup"
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr "Rileva automaticamente i dispositivi immagine"
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr "Automazione"
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr "Backup"
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr "Nome della cartella di backup:"
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr "Locazione del backup:"
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr "Backup delle foto durante il download"
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+"Scelta della cartella di download. Sottocartelle per le fotografie scaricate "
+"saranno create automaticamente in questa cartella utilizzando la struttura "
+"specificata sotto."
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+"Scelta se saltare il download dell'immagine, oppure aggiungere un "
+"identificatore univoco."
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr "Copyright Damon Lynch 2007-09"
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr "Giorno iniziale:"
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr "Download / Pausa"
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr "Cartella di Download"
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr "Cartella di download:"
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr "Downloads oggi:"
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr "Gestione Errori"
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr "Registrazione degli Errori"
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr ""
+"Termina il programma al termine del completamento di un download con esito "
+"positivo"
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+"Se si disabilita il rilevamento automatico, scegliere l'esatta locazione del "
+"backup."
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+"Se si disabilita il rilevamento automatico, scegliere l'esatta locazione "
+"delle immagini."
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+"Se abiliti il riconoscimento automatico dei dispositivi di memorizzazione "
+"portatile (PSD), tutto il dispositivo sarà sottoposto a scansione per le "
+"immagini. Su dispositivi capienti ciò potrebbe richiedere tempo."
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr "Ignora"
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr "Dispositivi Immagine"
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr "Rinomina Immagini"
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+"I dispositivi immaginw sono dispositivi da cui scaricare fotografie, come "
+"macchine fotografiche, schede di memoria o dispositivi di memorizzazione "
+"portatili (PSD).\n"
+"\n"
+"Puoi scaricare fotografie da più dispositivi immagine contemporaneamente.\n"
+"\n"
+"<i>Se il download diretto dalla tua macchina fotografica funziona male o non "
+"funziona per niente, prova ad impostarla in modalità PTP. Se questo non "
+"fosse possibile, considera di utilizzare un lettore di schede di memoria.</i>"
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr "Locazione dell'immagine"
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr "Importa le tue immagini in modo efficiente ed affidabile"
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr "Sovrascrivi"
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr "Preferenze: Rapid Photo Downloader"
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+"Rapid Photo Downloader è software libero; puoi ridistribuirlo e/o "
+"modificarlo alle condizioni della GNU General Public License come pubblicato "
+"dalla Free Software Foundation; o la versione 2 della Licenza, o (a tua "
+"scelta) ogni versione successiva.\n"
+" \n"
+"Rapid Photo Downloader è distributed nella speranza che sarà utile, ma SENZA "
+"NESSUNA GARANZIA; anche senza la garanzia implicita di COMMERCIABILITA' o "
+"IDONEITA' PER UNO SCOPO PARTICOLARE. Vedi la GNU General Public License per "
+"dettagli ulteriori.\n"
+"\n"
+"Dovresti aver ricevuto una copia della GNU General Public License con Rapid "
+"Photo Downloader; altrimenti, scrivi alla Free Software Foundation, Inc., 51 "
+"Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr "Opzioni di Rinomina"
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr "Riporta una segnalazione"
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr "Riporta un errore"
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr "Salta"
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr "Salta il download"
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+"Specifica la cartella nella quale i backups sono memorizzati sul "
+"dispositivo. \n"
+"\n"
+"<i>Nota: questa sarà anche usata per determinare se un dispositivo è "
+"utilizzato per i backups o meno. Per ogni dispositivo che si vuol utilizzare "
+"per il backup, crearvi una cartella con questo nome.</i>"
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+"Specificare l'ora nel formato 24 ore a cui il numero di sequenza "
+"<i>Downloads oggi</i> dovrebbe essere reimpostato."
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+"Specificare cosa fare quando un'immagine con lo stesso nome è già stata "
+"scaricata o salvata."
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr "Specificare cosa fare quando non ci sono dispositivi di backup."
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+"Specificare se l'immagine o i nomi di cartella dovrebbero avere rimossi i "
+"caratteri non permessi da altri sistemi operativi."
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr "Inizia il download all'avvio del programma"
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr "Inizia il download all'inserimento di un dispositivo immagini"
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr "Numero memorizzato:"
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr "Elimina caratteri incompatibili"
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr "Smonta (\"espelle\") il dispositivo immagini al termine del download"
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+"Quando si effettua il backup, scegliere se sovrascrivere un'immagine che ha "
+"lo stesso nome sul dispositivo di backup, o se saltarne il backup."
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+"Si possono salvare in locazioni diverse le proprie fotografie mentre vengono "
+"scaricate, ad esempio un dischi esterni."
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr "_Svotare i Downloads Completati"
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr "_Registrazione Errori"
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr "_Richiedi Aiuto In Linea..."
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr "_Aiuto"
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr "_Fai una Donazione..."
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr "_Fotografie"
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr "_Segnala un Problema..."
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr "_Miniature"
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr "_Traduci questa Applicazione..."
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr "_Visualizzazione"
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr "si pregano i traduttori di ignorare questo"
+
+#~ msgid "Resequence"
+#~ msgstr "Riordinamento"
+
+#~ msgid ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>"
+#~ msgstr ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>\n"
+#~ "Marco Solari <marcosolari@gmail.com>"
+
+#~ msgid "gtk-help"
+#~ msgstr "Aiuto-gtk"
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..c228fc2
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,1426 @@
+# Polish translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: 2009-06-01 19:36+0000\n"
+"Last-Translator: mmiicc <mpredotka@gmail.com>\n"
+"Language-Team: Polish <pl@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-06-02 06:24+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr "Rapid Photo Downloader"
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr "Nieprawidłowa wartość Pobierań dzisiaj.\n"
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr "Resetowanie wartości do zera.\n"
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr "Wartość preferencji \"Początek dnia\" jest uszkodzona.\n"
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr "Resetowanie do północy.\n"
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr "Błąd w preferencjach zmiany nazw obrazów"
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr "Przepraszamy, te preferencje zawierają błąd:\n"
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr "Resetowanie do wartości domyślnych."
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr "Błąd w preferencjach podkatalogu pobierania"
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr "Wybór katalogu dla pobieranych zdjęć"
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr "Wybór katalogu obrazów"
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr "Wybór katalogu do utworzenia kopii zapasowej"
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+"<i><b>Ostrzeżenie:</b> Ilość metadanych jest niewystarczająca do pełnego "
+"wygenerowania nazwy. Proszę użyć innej opcji zmiany nazwy.</i>"
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+"<i><b>Ostrzeżenie:</b> Ilość metadanych jest niewystarczająca do pełnego "
+"wygenerowania podkatalogów. Proszę użyć innej opcji określenia nazwy "
+"podkatalogu </i>"
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr "<i>Przykład: %s</i>"
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr ""
+"Pewne niepotrzebne wartości zostały usunięte z preferencji podkatalogu."
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+"Wprowadzone preferencje podkatalogu są nieprawidłowe i nie mogą zostać "
+"użyte.\n"
+"Zostaną przywrócone ich domyślne wartości."
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr "dyskzewnętrzny1"
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr "dyskzewnętrzny2"
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr "wyszukiwanie..."
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr "Błąd w preferencjach programu."
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+"\n"
+"Proszę sprawdzić preferencje, uruchomić program ponownie i spróbować jeszcze "
+"raz."
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr "Pobieranie nie może się odbyć"
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr "skopiowano 0 z %s obrazów"
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+"Wyszukiwanie zakończone: w katalogu %(device)s znaleziono obrazów %(number)s"
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr "Wyszukiwanie zakończone: nie znaleziono obrazów w katalogu %s"
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr "Nazwa pliku obrazu nie mogła zostać wygenerowana"
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Źródło: %(source)s\n"
+"Problem: %(problem)s"
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Nazwa pliku obrazu nie mogła zostać prawidłowo wygenerowana. Proszę "
+"sprawdzić, czy metadane obrazu są wystarczające."
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Źródło: %(source)s\n"
+"Cel: %(destination)s\n"
+"Problem: %(problem)s"
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr "Nie można otworzyć obrazu"
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr "Źródło: %s"
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr "Obraz nie posiada metadanych"
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+"Metadane są niezbędne aby wygenerować nazw podkatalogów / obrazów.\n"
+"Źródło: %s"
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Nazwa podkatalogu nie mogła zostać prawidłowo wygenerowana. Proszę "
+"sprawdzić, czy metadane obrazu są wystarczające."
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Podkatalog: %(subfolder)s\n"
+"Obraz: %(image)s\n"
+"Problem: %(problem)s"
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+"Źródło: %(source)s\n"
+"Cel: %(destination)s"
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr "Dodano unikatowy identyfikator \"%s\""
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+"Rozpoczął się nowy dzień - resetowanie numeru sekwencji \"Pobierań dzisiaj\""
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr "Błąd pobierania"
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+"Źródło: %(source)s\n"
+"Cel: %(destination)s\n"
+"Błąd: %(errorno)s %(strerror)s"
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr "Obraz nie został skopiowany."
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr "Kopia zapasowa obrazu już istnieje"
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr "Błąd tworzenia kopii zapasowej"
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Nie można utworzyć katalogu docelowego\n"
+"%(directory)s\n"
+"Błąd: %(errno)s %(strerror)s"
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Źródło: %(source)s\n"
+"Cel: %(destination)s\n"
+"Błąd: %(errno)s %(strerror)s"
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr "Teraz można bezpiecznie usunąć urządzenie"
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr "obrazów pobranych: %s"
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr "obrazów pominiętych: %s"
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr "ostrzeżenia"
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr "błędy"
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr "Brak urządzenia do zapisu kopii zapasowej"
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr "Nie wykryto urządzenia na którym można utworzyć kopię zapasową"
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr "Ten nośnik nie zawiera obrazów, które można pobrać."
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr "Rozpoczęto pobieranie z %s"
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr "Obraz pominięto"
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr "Obraz nadpisano"
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr "Obraz już istnieje"
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr "Obraz nie posiada miniatury"
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr "Skopiowano %(number)s z %(total)s obrazów"
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr "Ukończono pobieranie z %s"
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr "Urządzenie"
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr "Rozmiar"
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr "Postęp pobierania"
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr "Nie można wyświetlić miniatury"
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr "Może być uszkodzone"
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr "Niektóre preferencje zostaną zresetowane."
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+"Nowsza wersja tego programu była poprzednio uruchomiona na tym komputerze.\n"
+"\n"
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+"Preferencje programu wydają się być właściwe, proszę jednak sprawdzić, czy "
+"zapewniają prawidłowe działanie."
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr ""
+"Przepraszamy, niektóre preferencje są nieprawidłowe i zostaną zresetowane."
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr "Ostrzeżenie:"
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+"Ta wersja programu jest nowsza od uruchomionej poprzednio. Sprawdzanie "
+"preferencji."
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr "Preferencje zostały zmodyfikowane."
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+"Ta wersja programu używa innych preferencji niż starsza wersja. Preferencje "
+"zostały zaktualizowane.\n"
+"\n"
+"Proszę je sprawdzić, czy zapewniają prawidłowe działanie."
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr "Żadne preferencje nie muszą zostać zmienione."
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+"Ta wersja programu używa innych preferencji niż starsza wersja. Niektóre z "
+"poprzednich preferencji były nieprawidłowe i nie mogły zostać "
+"zaktualizowane. Zostaną one zresetowane."
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr "Problem z użyciem pynotify."
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr "Pobranie właściwości serwera pynotify nieudane."
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr "oraz"
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr "Użycie urządzeń do zapisu kopii zapasowej"
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr "Użycie urządzenia do zapisu kopii zapasowej"
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr "Nie wykryto urządzeń na których można utworzyć kopię zapasową"
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr "Wykryto %(device)s ze ścieżką %(path)s"
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr "Automatyczne rozpoczęcie pobierania jest włączone"
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr "Automatyczne rozpoczęcie pobierania jest wyłączone"
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr "Użycie ręcznie wprowadzonej ścieżki"
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr "Ukończono wszystkie pobierania"
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr "MB/s"
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr "Pozostała około sekunda"
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr "Pozostało około %i sekund"
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr "Pozostała około minuta"
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr "Pozostało około %(minutes)i:%(seconds)02i minut"
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr "obrazów pobranych"
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr "obrazów pominiętych"
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr "_Pobierz "
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr "W_strzymaj"
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr "Preferencje zostały zmienione."
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr "Do zobaczenia"
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+"wyświetl informacje programu w linii komend podczas działania programu "
+"(domyślnie: %default)"
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr "wyświetlaj jedynie błędy w linii komend"
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr "wypisz typy plików rozpoznawane przez program i zakończ"
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr "oraz %s"
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr "Użycie"
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr "%s jest już uruchomiony"
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr "Data czas"
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr "Tekst"
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr "Nazwa pliku"
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr "Metadane"
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr "Sekwencje"
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr "Data zdjęcia"
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr "Dzisiaj"
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr "Wczoraj"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr "Nazwa + rozszerzenie"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr "Nazwa"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr "Rozszerzenie"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr "Numer obrazu"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr "Przysłona"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr "ISO"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr "Czas naświetlania"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr "Ogniskowa"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr "Producent aparatu"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr "Model aparatu"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr "Skrót modelu aparatu"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr "Skrót z myślnikiem modelu aparatu"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr "Numer seryjny"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr "Licznik migawki"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr "Nazwa właściciela"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr "Pobierań dzisiaj"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr "Numer sesji"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr "Numer podkatalogu"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr "Numer zachowany"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr "Litera sekwencji"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr "Wszystkie cyfry"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr "Ostatnia cyfra"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr "Ostatnie 2 cyfry"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr "Ostatnie 3 cyfry"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr "Ostatnie 4 cyfry"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr "Oryginalna wielkość liter"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr "WIELKIE LITERY"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr "małe litery"
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr "Jedna cyfra"
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr "Dwie cyfry"
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr "Trzy cyfry"
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr "Cztery cyfry"
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr "Pięć cyfr"
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr "Sześć cyfr"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr "Części sekundy"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr "RRRRMMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr "RRRR-MM-DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr "RRMMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr "RR-MM-DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr "MMDDRRRR"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr "MMDDRR"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr "MMDD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr "DDMMRRRR"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr "DDMMRR"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr "RRRR"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr "RR"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr "MM"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr "DD"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr "GGMMSS"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr "GGMM"
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+"Klucz preferencji \"%(key)s\" jest nieprawidłowy.\n"
+"Oczekiwano %(value)s"
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr "Wartość preferencji \"%(value)s\" jest nieprawidłowa"
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr "Następujące preferencje nie są dobrze sformułowane:"
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr "Obraz nie zawiera metadanych części sekundy"
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr "Obraz nie zawiera metadanych %s"
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr "Błąd w składniku data czas. Nieprawidłowa wartość %s"
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr ""
+"rozszerzenie zostało określone ale obraz nie posiada żadnego rozszerzenia"
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr ""
+"numer obrazu został określony ale nazwa pliku nie posiada żadnego numeru"
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr "błąd przy tworzeniu nazwy ze składową %s"
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr "Preferencje podkatalogu nie powinny zaczynać się od %s"
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr "Preferencje podkatalogu nie powinny kończyć się na %s"
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+"Preferencje podkatalogu nie powinny zawierać dwóch %s jeden po drugim"
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr " gg:mm"
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ":"
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr "<b>Kopia zapasowa</b>"
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr "<b>Zgodność z innymi systemami operacyjnymi</b>"
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr "<b>Katalog pobierania</b>"
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr "<b>Podkatalogi pobierania</b>"
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr "<b>Przykład</b>"
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr "<b>Nośniki obrazów</b>"
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr "<b>Konflikty nazw obrazów</b>"
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr "<b>Zmiana nazw obrazów</b>"
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr "<b>Brak urządzeń do zapisu kopii zapasowej</b>"
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr "<b>Automatyzacja programu</b>"
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr "<b>Numery sekwencji</b>"
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr "<i>/media/dyskzewnętrzny/Photos</i>"
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr "<i>Przykład: /home/user/photos</i>"
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr "<i>Przykład:</i>"
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr "<i>Nowa:</i>"
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr "<i>Oryginalna:</i>"
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Automatyzacja</span>"
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Kopia zapasowa</span>\t"
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Katalog pobierania</span>"
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Obsługa błędów</span>"
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Nośniki obrazów</span>"
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr "<span weight=\"bold\" size=\"x-large\">Zmiana nazw obrazów</span>\t"
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Opcje zmiany nazw</span>"
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr "Dodaj unikatowy identyfikator"
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr "Automatycznie wykryj przenośne magazyny danych"
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr ""
+"Automatycznie wykryj urządzenia na których można utworzyć kopię zapasową"
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr "Automatycznie wykryj nośniki obrazów"
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr "Automatyzacja"
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr "Kopia zapasowa"
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr "Nazwa katalogu z kopią zapasową:"
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr "Położenie kopii zapasowej:"
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr "Utwórz kopię zapasową podczas pobierania zdjęć"
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+"Proszę wybrać katalog pobierania. Podkatalogi dla pobranych zdjęć zostaną w "
+"nim automatycznie utworzone w oparciu o poniższą specyfikację."
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+"Proszę wybrać czy pominąć pobieranie obrazu, czy dodać unikatowy "
+"identyfikator."
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr "Copyright Damon Lynch 2007-09"
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr "Początek dnia:"
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr "Pobierz / Wstrzymaj"
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr "Katalog pobierania"
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr "Katalog pobierania:"
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr "Pobierań dzisiaj:"
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr "Obsługa błędów"
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr "Dziennik błędów"
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr "Zakończ działanie programu po udanym ukończeniu pobierania"
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+"W przypadku wyłączenia wykrywania automatycznego, proszę określić dokładne "
+"położenie kopii zapasowej."
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+"W przypadku wyłączenia wykrywania automatycznego, proszę wybrać dokładne "
+"położenie obrazów."
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+"Jeżeli automatyczne wykrywanie przenośnych magazynów danych jest aktywne, "
+"obrazy będą wyszukiwane na całym nośniku. W przypadku nośników o dużych "
+"pojemnościach, może to chwilę potrwać."
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr "Ignoruj"
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr "Nośniki obrazów"
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr "Zmiana nazw obrazów"
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+"Nośniki obrazów to urządzenia z których można pobrać zdjęcia, takie jak "
+"aparaty fotograficzne, karty pamięci czy przenośne magazyny danych,\n"
+"\n"
+"Zdjęcia mogą być pobierane jednocześnie z kilku nośników obrazów.\n"
+"\n"
+"<i>Jeżeli pobieranie bezpośrednio z aparatu fotograficznego działa "
+"nieprawidłowo lub wcale, proszę spróbować przestawić go na tryb PTP. Jeśli "
+"jest to niemożliwe, proszę rozważyć użycie czytnika kart pamięci.</i>"
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr "Położenie obrazów:"
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr "Importuj obrazy wydajnie i niezawodnie"
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr "Nadpisz"
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr "Preferencje: Rapid Photo Downloader"
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+"Program Rapid Photo Downloader jest wolnym oprogramowaniem; można go "
+"rozprowadzać dalej i/lub modyfikować na warunkach Powszechnej Licencji "
+"Publicznej GNU, wydanej przez Fundację Wolnego Oprogramowania - według "
+"wersji drugiej tej Licencji lub którejś z późniejszych wersji.\n"
+"\n"
+"Program Rapid Photo Downloade rozpowszechniany jest z nadzieją, iż będzie on "
+"użyteczny - jednak BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji "
+"PRZYDATNOŚCI HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ. W celu "
+"uzyskania bliższych informacji należy zapoznać się z Powszechną Licencją "
+"Publiczną GNU.\n"
+"\n"
+"Z pewnością wraz z niniejszym programem dostarczono także egzemplarz "
+"Powszechnej Licencji Publicznej GNU (GNU General Public License); jeśli nie -"
+" proszę napisać do Free Software Foundation, Inc., 51 Franklin Street, Fifth "
+"Floor, Boston, MA 02110-130159 USA"
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr "Opcje zmiany nazw"
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr "Zgłoś ostrzeżenie"
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr "Zgłoś błąd"
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr "Pomiń"
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr "Pomiń pobieranie"
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+"Proszę określić katalog dla tego urządzenia w którym przechowywana będzie "
+"kopia zapasowa. \n"
+"\n"
+"<i>Uwaga: zostanie to również wykorzystane do określenia czy urządzenie "
+"będzie używane do tworzenia kopii zapasowych. Proszę utworzyć katalog o "
+"podanej nazwie dla każdego urządzenia, które będzie używane do zapisu kopii "
+"zapasowych.</i>"
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+"Proszę określić czas, w formacie 24-godzinnym, w którym numer sekwencji "
+"<i>Pobierań dzisiaj</i> powinien zostać zresetowany."
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+"Proszę określić zachowanie w przypadku, kiedy obraz o tej samej nazwie "
+"został już pobrany lub posiada kopię zapasową."
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr ""
+"Proszę określić zachowanie w przypadku braku urządzeń na których można "
+"utworzyć kopię zapasową."
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+"Proszę określić czy znaki, które są niedozwolone przez inne systemy "
+"operacyjne, powinny zostać usunięte z nazw obrazów i katalogów."
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr "Rozpocznij pobieranie przy uruchomieniu programu"
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr "Rozpocznij pobieranie po podłączeniu nośnika zdjęć"
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr "Numer zachowany:"
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr "Usuń niezgodne znaki"
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr "Odmontuj (\"wysuń\") nośnik zdjęć po ukończeniu pobierania"
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+"Proszę wybrać, czy podczas tworzenia kopii zapasowej nadpisać, czy pominąć "
+"obraz o tej samej nazwie na urządzeniu docelowym."
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+"Możliwe jest utworzenie wielu kopii zapasowych dla pobieranych zdjęć, np. na "
+"zewnętrznych dyskach twardych."
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr "Wyczyść _ukończone pobierania"
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr "_Dziennik błędów"
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr "Z_najdź pomoc w sieci..."
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr "_Pomoc"
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr "_Darowizna"
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr "_Zdjęcia"
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr "Zgłoś _błąd w programie..."
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr "_Miniatury"
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr "_Przetłumacz ten program..."
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr "_Widok"
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr ""
+
+#~ msgid ""
+#~ "There is an error in the program preferences.\n"
+#~ "Please check preferences, restart the program, and try again."
+#~ msgstr ""
+#~ "W preferencjach programu jest błąd.\n"
+#~ "Proszę sprawdzić preferencje, uruchomić program ponownie i jeszcze raz "
+#~ "spróbować."
+
+#~ msgid ""
+#~ "Image devices are devices from which to download photos, such as memory "
+#~ "cards or Portable Storage Devices.\n"
+#~ "\n"
+#~ "You can download photos from multiple image devices simultaneously."
+#~ msgstr ""
+#~ "Nośniki obrazów to urządzenia z których można pobrać zdjęcia, takie jak "
+#~ "karty pamięci czy przenośne magazyny danych.\n"
+#~ "\n"
+#~ "Zdjęcia mogą być pobierane jednocześnie z kilku nośników obrazów."
+
+#~ msgid ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>"
+#~ msgstr ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>"
+
+#~ msgid ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Daniel Plasser <daniel@paessler.org>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>\n"
+#~ "Marco Solari <marcosolari@gmail.com>"
+#~ msgstr ""
+#~ "Julien Valroff <julien@kirya.net>\n"
+#~ "Michal Predotka <mpredotka@googlemail.com>\n"
+#~ "Martin Egger <martin.egger@gmx.net>\n"
+#~ "Daniel Plasser <daniel@paessler.org>\n"
+#~ "Abel O'Rian <abel.orian@gmail.com>\n"
+#~ "Jose Luis Navarro <jlnavarro111@gmail.com>\n"
+#~ "Marco Solari <marcosolari@gmail.com>"
diff --git a/po/rapid-photo-downloader.pot b/po/rapid-photo-downloader.pot
new file mode 100644
index 0000000..d3c9f0e
--- /dev/null
+++ b/po/rapid-photo-downloader.pot
@@ -0,0 +1,1268 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr ""
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr ""
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr ""
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr ""
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr ""
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr ""
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr ""
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr ""
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr ""
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr ""
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr ""
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr ""
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr ""
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr ""
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr ""
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr ""
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr ""
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr ""
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr ""
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr ""
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr ""
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr ""
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr ""
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr ""
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr ""
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr ""
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr ""
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr ""
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr ""
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr ""
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr ""
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr ""
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr ""
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr ""
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr ""
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr ""
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr ""
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr ""
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr ""
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr ""
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr ""
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr ""
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr ""
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr ""
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr ""
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr ""
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr ""
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr ""
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr ""
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr ""
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr ""
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr ""
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr ""
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr ""
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr ""
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr ""
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr ""
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr ""
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr ""
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr ""
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr ""
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr ""
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr ""
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr ""
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr ""
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr ""
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr ""
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr ""
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr ""
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr ""
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr ""
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr ""
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr ""
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr ""
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr ""
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr ""
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr ""
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr ""
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr ""
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr ""
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr ""
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr ""
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr ""
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr ""
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr ""
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr ""
diff --git a/po/ru.po b/po/ru.po
new file mode 100644
index 0000000..12bf648
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,1378 @@
+# Russian translation for rapid
+# Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009
+# This file is distributed under the same license as the rapid package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2009.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: rapid\n"
+"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
+"POT-Creation-Date: 2009-05-30 14:31+0800\n"
+"PO-Revision-Date: 2009-06-02 18:47+0000\n"
+"Last-Translator: Sergei Sedov <sedov@webmail.perm.ru>\n"
+"Language-Team: Russian <ru@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Launchpad-Export-Date: 2009-06-04 11:00+0000\n"
+"X-Generator: Launchpad (build Unknown)\n"
+
+#. Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+#: rapid/rapid.py:100 rapid/glade3/rapid.glade.h:63
+msgid "Rapid Photo Downloader"
+msgstr "Rapid Photo Downloader"
+
+#: rapid/rapid.py:392
+msgid "Invalid Downloads Today value.\n"
+msgstr "Неверное значение 'Скачиваний сегодня'.\n"
+
+#: rapid/rapid.py:393
+msgid "Resetting value to zero.\n"
+msgstr "Сбросить значение до нуля.\n"
+
+#: rapid/rapid.py:432
+msgid "'Start of day' preference value is corrupted.\n"
+msgstr "Значение 'Начало дня' повреждено.\n"
+
+#: rapid/rapid.py:433
+msgid "Resetting to midnight.\n"
+msgstr "Сброс настроек в полночь.\n"
+
+#: rapid/rapid.py:457
+msgid "Error in Image Rename preferences"
+msgstr "Ошибка в параметрах настройки переименования фотографий"
+
+#: rapid/rapid.py:466 rapid/rapid.py:1186
+msgid "Sorry,these preferences contain an error:\n"
+msgstr "Извините, эти параметры содержат ошибку:\n"
+
+#: rapid/rapid.py:477
+msgid "Resetting to default values."
+msgstr "Восстановить настройки по умолчанию."
+
+#: rapid/rapid.py:612
+msgid "Error in Download Subfolder preferences"
+msgstr "Ошибка в параметрах настройки подкаталогов для сохранения"
+
+#: rapid/rapid.py:746
+msgid "Select a folder to download photos to"
+msgstr "Выберите каталог для сохранения фотографий"
+
+#: rapid/rapid.py:793
+msgid "Select an image folder"
+msgstr "Выберите каталог с фотографиями"
+
+#: rapid/rapid.py:815
+msgid "Select a folder in which to backup images"
+msgstr "Выберите каталог для сохранения резервных копий фотографий"
+
+#. Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+#: rapid/rapid.py:904
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"the name. Please use other renaming options.</i>"
+msgstr ""
+"<i><b>Внимание:</b> Не хватает метаданных для генерирования названий "
+"фотографий. Пожалуйста, используйте другие параметры переименования.</i>"
+
+#: rapid/rapid.py:924
+msgid ""
+"<i><b>Warning:</b> There is insufficient image metatdata to fully generate "
+"subfolders. Please use other subfolder naming options.</i>"
+msgstr ""
+"<i><b>Внимание:</b> Не хватает метаданных для генерирования названий "
+"подкаталогов. Пожалуйста, используйте другие параметры переименования.</i>"
+
+#. Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+#: rapid/rapid.py:928
+#, python-format
+msgid "<i>Example: %s</i>"
+msgstr "<i>Пример: %s</i>"
+
+#: rapid/rapid.py:983
+msgid "The subfolder preferences had some unnecessary values removed."
+msgstr ""
+"Параметры подкаталогов, имеющих некоторые ненужные значения, были удалены."
+
+#. Preferences list is now empty
+#: rapid/rapid.py:988
+msgid ""
+"The subfolder preferences entered are invalid and cannot be used.\n"
+"They will be reset to their default values."
+msgstr ""
+"Введённые параметры подкаталога неправильны и не могут быть использованы.\n"
+"Они будут сброшены до значений принятых по умолчанию."
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1116
+msgid "externaldrive1"
+msgstr "внешний диск 1"
+
+#. Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+#: rapid/rapid.py:1118
+msgid "externaldrive2"
+msgstr "внешний диск 2"
+
+#. This refers to when a device like a hard drive is having its contents scanned,
+#. looking for images. It is visible initially in the progress bar for each device
+#. (which normally holds "x of y images copied").
+#. It maybe displayed only briefly if the contents of the device being scanned is small.
+#: rapid/rapid.py:1175
+msgid "scanning..."
+msgstr "сканирование..."
+
+#: rapid/rapid.py:1264 rapid/rapid.py:2222
+msgid "There is an error in the program preferences."
+msgstr "Обнаружена ошибка в параметрах программы."
+
+#: rapid/rapid.py:1265
+msgid ""
+"\n"
+"Please check preferences, restart the program, and try again."
+msgstr ""
+"\n"
+"Пожалуйста, проверьте параметры, перезапустите программу и попробуйте снова."
+
+#: rapid/rapid.py:1266 rapid/rapid.py:1267
+msgid "Download cannot proceed"
+msgstr "Невозможно осуществить скачивание"
+
+#. Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+#. It refers to the actual number of images that can be copied. For example, the user might see the following:
+#. '0 of 512 images copied'.
+#. This particular text is displayed to the user before the download has started.
+#: rapid/rapid.py:1303 rapid/rapid.py:1876
+#, python-format
+msgid "0 of %s images copied"
+msgstr "0 из %s фотографий скопировано"
+
+#. Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+#. This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+#. to the user when they run the program, signifying the number of images found, and the device they were found on.
+#. %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+#. not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+#. in a sentence, but you should never modify them or leave them out.
+#: rapid/rapid.py:1315
+#, python-format
+msgid "Device scan complete: found %(number)s images on %(device)s"
+msgstr ""
+"Сканирование носителя завершено: найдено %(number)s фотографий на %(device)s"
+
+#: rapid/rapid.py:1321
+#, python-format
+msgid "Device scan complete: no images found on %s"
+msgstr "Сканирование носителя %s завершено: фотографий не найдено"
+
+#: rapid/rapid.py:1352
+msgid "Image filename could not be generated"
+msgstr "Не смог сгенерировать название фотографии"
+
+#. '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+#: rapid/rapid.py:1354
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Источник: %(source)s\n"
+"Проблема: %(problem)s"
+
+#: rapid/rapid.py:1358
+msgid ""
+"Image filename could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Название фотографии не получилось сгенерировать должным образом. Проверьте "
+"достаточно ли метаданных."
+
+#: rapid/rapid.py:1359
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Источник: %(source)s\n"
+"Получатель: %(destination)s\n"
+"Проблема: %(problem)s"
+
+#: rapid/rapid.py:1368
+msgid "Could not open image"
+msgstr "Не смог открыть фотографию"
+
+#: rapid/rapid.py:1369
+#, python-format
+msgid "Source: %s"
+msgstr "Источник: %s"
+
+#: rapid/rapid.py:1378
+msgid "Image has no metadata"
+msgstr "Фотография не содержит метаданных"
+
+#: rapid/rapid.py:1379
+#, python-format
+msgid ""
+"Metadata is essential for generating subfolders / image names.\n"
+"Source: %s"
+msgstr ""
+"Метаданные необходимы для генерирования названий подкаталогов / "
+"фотографий.\n"
+"Источник: %s"
+
+#: rapid/rapid.py:1391
+msgid ""
+"Subfolder name could not be properly generated. Check to ensure there is "
+"sufficient image metadata."
+msgstr ""
+"Название подкаталога не получилось сгенерировать должным образом. Проверьте "
+"достаточно ли метаданных."
+
+#: rapid/rapid.py:1392
+#, python-format
+msgid ""
+"Subfolder: %(subfolder)s\n"
+"Image: %(image)s\n"
+"Problem: %(problem)s"
+msgstr ""
+"Подкаталог: %(subfolder)s\n"
+"Фотография: %(image)s\n"
+"Проблема: %(problem)s"
+
+#: rapid/rapid.py:1444 rapid/rapid.py:1472 rapid/rapid.py:1491
+#: rapid/rapid.py:1553
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s"
+msgstr ""
+"Источник: %(source)s\n"
+"Получатель: %(destination)s"
+
+#: rapid/rapid.py:1493
+#, python-format
+msgid "Unique identifier '%s' added"
+msgstr "Добавлен уникальный идентификатор '%s'"
+
+#. A new day, according the user's preferences of what time a day begins, has started
+#: rapid/rapid.py:1510
+msgid "New day has started - resetting 'Downloads Today' sequence number"
+msgstr ""
+"Начался новый день - сброшена последовательность номеров параметра "
+"'Скачиваний сегодня'"
+
+#: rapid/rapid.py:1515 rapid/rapid.py:1521
+msgid "Download copying error"
+msgstr "Ошибка при закачке файлов"
+
+#: rapid/rapid.py:1516
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errorno)s %(strerror)s"
+msgstr ""
+"Источник: %(source)s\n"
+"Получатель: %(destination)s\n"
+"Ошибка: %(errorno)s %(strerror)s"
+
+#: rapid/rapid.py:1518 rapid/rapid.py:1591
+msgid "The image was not copied."
+msgstr "Фотография не скопирована."
+
+#: rapid/rapid.py:1552
+msgid "Backup image already exists"
+msgstr "Носитель для резервного копирования фотографий уже существует"
+
+#: rapid/rapid.py:1580 rapid/rapid.py:1588 rapid/rapid.py:1594
+msgid "Backing up error"
+msgstr "Ошибка резервного копирования"
+
+#: rapid/rapid.py:1581
+#, python-format
+msgid ""
+"Destination directory could not be created\n"
+"%(directory)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Невозможно создать каталог получателя\n"
+"%(directory)s\n"
+"Ошибка: %(errno)s %(strerror)s"
+
+#: rapid/rapid.py:1589 rapid/rapid.py:1595
+#, python-format
+msgid ""
+"Source: %(source)s\n"
+"Destination: %(destination)s\n"
+"Error: %(errno)s %(strerror)s"
+msgstr ""
+"Источник: %(source)s\n"
+"Получатель: %(destination)s\n"
+"Ошибка: %(errno)s %(strerror)s"
+
+#. This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+#: rapid/rapid.py:1608
+msgid "The device can now be safely removed"
+msgstr "Теперь можно безопасно отсоединить носитель"
+
+#: rapid/rapid.py:1612
+#, python-format
+msgid "%s images downloaded"
+msgstr "%s фотографий скачано"
+
+#: rapid/rapid.py:1614
+#, python-format
+msgid "%s images skipped"
+msgstr "%s фотографий пропущено"
+
+#: rapid/rapid.py:1620 rapid/rapid.py:2707
+msgid "warnings"
+msgstr "предупреждения"
+
+#: rapid/rapid.py:1622 rapid/rapid.py:2709
+msgid "errors"
+msgstr "ошибки"
+
+#: rapid/rapid.py:1644
+msgid "Backup device missing"
+msgstr "Пропущен носитель для резервного копирования"
+
+#: rapid/rapid.py:1644
+msgid "No backup device was detected."
+msgstr "Устройство для сохранения резервных копий не обнаружено"
+
+#: rapid/rapid.py:1648
+msgid "This device has no images to download from."
+msgstr "На этом устройстве не обнаружены фотографии, которые можно скачать."
+
+#: rapid/rapid.py:1674
+#, python-format
+msgid "Download has started from %s"
+msgstr "Начато скачивание с %s"
+
+#: rapid/rapid.py:1711
+msgid "Image skipped"
+msgstr "Фотография пропущена"
+
+#: rapid/rapid.py:1712
+msgid "Image overwritten"
+msgstr "Фотография перезаписана"
+
+#: rapid/rapid.py:1713
+msgid "Image already exists"
+msgstr "Фотография уже существует"
+
+#: rapid/rapid.py:1758
+msgid "Image has no thumbnail"
+msgstr "У фотографии нет предпросмотра"
+
+#: rapid/rapid.py:1768
+#, python-format
+msgid "%(number)s of %(total)s images copied"
+msgstr "%(number)s из %(total)s фотографий скопировано"
+
+#: rapid/rapid.py:1784
+#, python-format
+msgid "Download complete from %s"
+msgstr "Скачивание с %s завершено"
+
+#. Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+#: rapid/rapid.py:1860
+msgid "Device"
+msgstr "Носитель"
+
+#. Size refers to the total size of images on the device, typically in MB or GB
+#: rapid/rapid.py:1865
+msgid "Size"
+msgstr "Размер"
+
+#: rapid/rapid.py:1868
+msgid "Download Progress"
+msgstr "Скачано"
+
+#: rapid/rapid.py:1984 rapid/rapid.py:1990
+msgid "Thumbnail cannot be displayed"
+msgstr "Предпросмотр фотографии не может быть выполнен"
+
+#: rapid/rapid.py:1985 rapid/rapid.py:1991
+msgid "It may be corrupted"
+msgstr "Возможно он повреждён"
+
+#: rapid/rapid.py:2223
+msgid "Some preferences will be reset."
+msgstr "Некоторые параметры будут сброшены."
+
+#: rapid/rapid.py:2251
+msgid ""
+"A newer version of this program was previously run on this computer.\n"
+"\n"
+msgstr ""
+"На этом компьютере ранее запускалась более новая версия программы.\n"
+"\n"
+
+#: rapid/rapid.py:2253
+msgid ""
+"Program preferences appear to be valid, but please check them to ensure "
+"correct operation."
+msgstr ""
+"Параметры программы кажется корректны, но, пожалуйста, проверьте их, чтобы "
+"быть уверенными в правильности."
+
+#: rapid/rapid.py:2255
+msgid "Sorry, some preferences are invalid and will be reset."
+msgstr "Извините, некоторые параметры были неправильными и будут сброшены."
+
+#: rapid/rapid.py:2256
+msgid "Warning:"
+msgstr "Предупреждение:"
+
+#: rapid/rapid.py:2261
+msgid ""
+"This version of the program is newer than the previously run version. "
+"Checking preferences."
+msgstr ""
+"Эта версия программы новее чем запущенная ранее. Проверьте параметры."
+
+#: rapid/rapid.py:2268
+msgid "Preferences were modified."
+msgstr "Параметры были изменены"
+
+#: rapid/rapid.py:2269
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Your preferences have been updated.\n"
+"\n"
+"Please check them to ensure correct operation."
+msgstr ""
+"Эта версия программы использует несколько другие параметры, чем предыдущая. "
+"Параметры были автоматически обновлены.\n"
+"\n"
+"Пожалуйста, проверьте их, чтобы быть уверенными, что всё прошло правильно."
+
+#: rapid/rapid.py:2273
+msgid "No preferences needed to be changed."
+msgstr "Отсутствуют параметры, которые необходимо было бы изменить."
+
+#: rapid/rapid.py:2275
+msgid ""
+"This version of the program uses different preferences than the old version. "
+"Some of your previous preferences were invalid, and could not be updated. "
+"They will be reset."
+msgstr ""
+"Эта версия программы использует несколько другие параметры, чем предыдущая. "
+"Некоторые из ваших параметров были не верными. Они будут сброшены."
+
+#: rapid/rapid.py:2284
+msgid "Problem using pynotify."
+msgstr "Проблема при использовании pynotify."
+
+#: rapid/rapid.py:2300
+msgid "Failed to receive pynotify server capabilities."
+msgstr "Не удалось получить возможности сервера pynotify."
+
+#: rapid/rapid.py:2338
+msgid "and"
+msgstr "и"
+
+#: rapid/rapid.py:2343
+msgid "Using backup devices"
+msgstr "Использование носителя для резервного копирования"
+
+#: rapid/rapid.py:2345
+msgid "Using backup device"
+msgstr "Использование носителя для резервного копирования"
+
+#: rapid/rapid.py:2347
+msgid "No backup devices detected"
+msgstr "Не обнаружено носителей для создания резервных копий"
+
+#: rapid/rapid.py:2482
+#, python-format
+msgid "Detected %(device)s with path %(path)s"
+msgstr "Обнаружено %(device)s с путём %(path)s"
+
+#: rapid/rapid.py:2486
+msgid "Automatically start download is true"
+msgstr "Автоматически начинать скачивание - да"
+
+#: rapid/rapid.py:2488
+msgid "Automatically start download is false"
+msgstr "Автоматически начинать скачивание - нет"
+
+#: rapid/rapid.py:2536
+msgid "Using manually specified path"
+msgstr "Использовать путь, который указан вручную"
+
+#: rapid/rapid.py:2653 rapid/rapid.py:2702
+msgid "All downloads complete"
+msgstr "Все скачивания завершены"
+
+#: rapid/rapid.py:2667
+msgid "MB/s"
+msgstr "Мб/с"
+
+#: rapid/rapid.py:2677
+msgid "About 1 second remaining"
+msgstr "Осталась примерно 1 секунда"
+
+#: rapid/rapid.py:2679
+#, python-format
+msgid "About %i seconds remaining"
+msgstr "Осталось %i секунд"
+
+#: rapid/rapid.py:2681
+msgid "About 1 minute remaining"
+msgstr "Осталась примерно 1 минута"
+
+#. Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+#. '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+#. of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+#: rapid/rapid.py:2686
+#, python-format
+msgid "About %(minutes)i:%(seconds)02i minutes remaining"
+msgstr "Осталось примерно %(minutes)i:%(seconds)02i"
+
+#: rapid/rapid.py:2703
+msgid "images downloaded"
+msgstr "фотографий скачано"
+
+#: rapid/rapid.py:2705
+msgid "images skipped"
+msgstr "фотографий пропущено"
+
+#. This text will be displayed to the user on the Download / Pause button.
+#. Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+#: rapid/rapid.py:2797
+msgid "_Download "
+msgstr "_Скачать "
+
+#. This text will be displayed to the user on the Download / Pause button.
+#: rapid/rapid.py:2807
+msgid "_Pause"
+msgstr "_Пауза"
+
+#: rapid/rapid.py:2862
+msgid "Preferences were changed."
+msgstr "Параметры были изменены"
+
+#: rapid/rapid.py:2993
+msgid "Goodbye"
+msgstr "До свидания"
+
+#. Translators: this text is displayed to the user when they request information on the command line options.
+#. The text %default should not be modified or left out.
+#: rapid/rapid.py:3004
+#, python-format
+msgid ""
+"display program information on the command line as the program runs "
+"(default: %default)"
+msgstr ""
+"отобразить информацию о программе в командной строке при запуске программы "
+"(по умолчанию: %default)"
+
+#: rapid/rapid.py:3005
+msgid "only output errors to the command line"
+msgstr "выводить в командную строку только ошибки"
+
+#. image file extensions are recognized RAW files plus TIFF and JPG
+#: rapid/rapid.py:3007
+msgid "list image file extensions the program recognizes and exit"
+msgstr ""
+"вывести расширения файла фотографии, которые распознала программа и выйти"
+
+#: rapid/rapid.py:3020
+#, python-format
+msgid "and %s"
+msgstr "и %s"
+
+#. Which volume management code is being used (GIO or GnomeVFS)
+#: rapid/rapid.py:3025 rapid/rapid.py:3028
+msgid "Using"
+msgstr "Использование"
+
+#. this application is already running
+#: rapid/rapid.py:3042
+#, python-format
+msgid "%s is already running"
+msgstr "%s уже запущено"
+
+#: rapid/renamesubfolderprefs.py:176
+msgid "Date time"
+msgstr "Дата и время"
+
+#: rapid/renamesubfolderprefs.py:177
+msgid "Text"
+msgstr "Текст"
+
+#: rapid/renamesubfolderprefs.py:178
+msgid "Filename"
+msgstr "Имя файла"
+
+#: rapid/renamesubfolderprefs.py:179
+msgid "Metadata"
+msgstr "Метаданные"
+
+#: rapid/renamesubfolderprefs.py:180
+msgid "Sequences"
+msgstr "Последовательности"
+
+#: rapid/renamesubfolderprefs.py:181
+msgid "Image date"
+msgstr "Дата фотографии"
+
+#: rapid/renamesubfolderprefs.py:182
+msgid "Today"
+msgstr "Сегодня"
+
+#: rapid/renamesubfolderprefs.py:183
+msgid "Yesterday"
+msgstr "Вчера"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:185
+msgid "Name + extension"
+msgstr "Имя + расширение"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:187
+msgid "Name"
+msgstr "Имя"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:189
+msgid "Extension"
+msgstr "Расширение"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:191
+msgid "Image number"
+msgstr "Номер фотографии"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:193
+msgid "Aperture"
+msgstr "Диафрагма"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:195
+msgid "ISO"
+msgstr "ISO"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:197
+msgid "Exposure time"
+msgstr "Время выдержки"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:199
+msgid "Focal length"
+msgstr "Фокусное расстояние"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:201
+msgid "Camera make"
+msgstr "Производитель камеры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:203
+msgid "Camera model"
+msgstr "Модель камеры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:205
+msgid "Short camera model"
+msgstr "Сокращённое название камеры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:207
+msgid "Hyphenated short camera model"
+msgstr "Расширенное название камеры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:209
+msgid "Serial number"
+msgstr "Серийный номер"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:211
+msgid "Shutter count"
+msgstr "Счётчик кадров"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+#: rapid/renamesubfolderprefs.py:213
+msgid "Owner name"
+msgstr "Имя владельца"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:215
+msgid "Downloads today"
+msgstr "Скачиваний сегодня"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:217
+msgid "Session number"
+msgstr "Номер сессии"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:219
+msgid "Subfolder number"
+msgstr "Номер подкаталога"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+#: rapid/renamesubfolderprefs.py:221
+msgid "Stored number"
+msgstr "Сохранение под номером"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+#: rapid/renamesubfolderprefs.py:223
+msgid "Sequence letter"
+msgstr "Последовательность символов"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:225
+msgid "All digits"
+msgstr "Все цифры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:227
+msgid "Last digit"
+msgstr "Последняя цифра"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:229
+msgid "Last 2 digits"
+msgstr "Последние 2 цифры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:231
+msgid "Last 3 digits"
+msgstr "Последние 3 цифры"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+#: rapid/renamesubfolderprefs.py:233
+msgid "Last 4 digits"
+msgstr "Последние 4 цифры"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:235
+msgid "Original Case"
+msgstr "Исходный Регистр"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:237
+msgid "UPPERCASE"
+msgstr "ВЕРХНИЙ РЕГИСТР"
+
+#. Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+#: rapid/renamesubfolderprefs.py:239
+msgid "lowercase"
+msgstr "нижний регистр"
+
+#: rapid/renamesubfolderprefs.py:240
+msgid "One digit"
+msgstr "Одна цифра"
+
+#: rapid/renamesubfolderprefs.py:241
+msgid "Two digits"
+msgstr "Две цифры"
+
+#: rapid/renamesubfolderprefs.py:242
+msgid "Three digits"
+msgstr "Три цифры"
+
+#: rapid/renamesubfolderprefs.py:243
+msgid "Four digits"
+msgstr "Четыре цифры"
+
+#: rapid/renamesubfolderprefs.py:244
+msgid "Five digits"
+msgstr "Пять цифр"
+
+#: rapid/renamesubfolderprefs.py:245
+msgid "Six digits"
+msgstr "Шесть цифр"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:247
+msgid "Subseconds"
+msgstr "Подсекунды"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:249
+msgid "YYYYMMDD"
+msgstr "ГГГГММДД"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:251
+msgid "YYYY-MM-DD"
+msgstr "ГГГГ-ММ-ДД"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:253
+msgid "YYMMDD"
+msgstr "ГГММДД"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:255
+msgid "YY-MM-DD"
+msgstr "ГГ-ММ-ДД"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:257
+msgid "MMDDYYYY"
+msgstr "ММДДГГГГ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:259
+msgid "MMDDYY"
+msgstr "ММДДГГ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:261
+msgid "MMDD"
+msgstr "ММДД"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:263
+msgid "DDMMYYYY"
+msgstr "ДДММГГГГ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:265
+msgid "DDMMYY"
+msgstr "ДДММГГ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:267
+msgid "YYYY"
+msgstr "ГГГГ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:269
+msgid "YY"
+msgstr "ГГ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:271
+msgid "MM"
+msgstr "ММ"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:273
+msgid "DD"
+msgstr "ДД"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:275
+msgid "HHMMSS"
+msgstr "ЧЧММСС"
+
+#. Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+#: rapid/renamesubfolderprefs.py:277
+msgid "HHMM"
+msgstr "ЧЧММ"
+
+#: rapid/renamesubfolderprefs.py:682
+#, python-format
+msgid ""
+"Preference key '%(key)s' is invalid.\n"
+"Expected one of %(value)s"
+msgstr ""
+"Неверен ключ параметров '%(key)s'.\n"
+"Ожидался один из %(value)s"
+
+#: rapid/renamesubfolderprefs.py:689
+#, python-format
+msgid "Preference value '%(value)s' is invalid"
+msgstr "Неверное значение параметра '%(value)s'"
+
+#: rapid/renamesubfolderprefs.py:693
+msgid "These preferences are not well formed:"
+msgstr "Эти параметры не очень хорошо подобраны:"
+
+#: rapid/renamesubfolderprefs.py:793
+msgid "Subsecond metadata not present in image"
+msgstr "Метаданные подсекунд не представлены в фотографии"
+
+#: rapid/renamesubfolderprefs.py:796 rapid/renamesubfolderprefs.py:919
+#, python-format
+msgid "%s metadata is not present in image"
+msgstr "%s метаданные не представлены в фотографии"
+
+#: rapid/renamesubfolderprefs.py:811
+#, python-format
+msgid "Error in date time component. Value %s appears invalid"
+msgstr "Ошибка в компоненте даты и времени. Значение %s неверно."
+
+#: rapid/renamesubfolderprefs.py:842
+msgid "extension was specified but image name has no extension"
+msgstr "расширение было указано, но фотографий не имеет расширения"
+
+#: rapid/renamesubfolderprefs.py:846
+msgid "image number was specified but image filename has no number"
+msgstr "номер фотографии был указано, но фотография не имеет номер"
+
+#: rapid/renamesubfolderprefs.py:1031
+#, python-format
+msgid "error generating name with component %s"
+msgstr "ошибка генерирования названия компонентом %s"
+
+#: rapid/renamesubfolderprefs.py:1327
+#, python-format
+msgid "Subfolder preferences should not start with a %s"
+msgstr "Параметры подкаталога не должны начинаться с %s"
+
+#: rapid/renamesubfolderprefs.py:1329
+#, python-format
+msgid "Subfolder preferences should not end with a %s"
+msgstr "Параметры подкаталога не должны заканчиваться с %s"
+
+#: rapid/renamesubfolderprefs.py:1333
+#, python-format
+msgid "Subfolder preferences should not contain two %s one after the other"
+msgstr "Параметры подкаталога не должны содержать две %s одну за другой"
+
+#: rapid/glade3/rapid.glade.h:1
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:2
+msgid " "
+msgstr " "
+
+#: rapid/glade3/rapid.glade.h:3
+msgid " hh:mm"
+msgstr " чч:мм"
+
+#: rapid/glade3/rapid.glade.h:4
+msgid ":"
+msgstr ":"
+
+#: rapid/glade3/rapid.glade.h:5
+msgid "<b>Backup</b>"
+msgstr "<b>Резервное копирование</b>"
+
+#: rapid/glade3/rapid.glade.h:6
+msgid "<b>Compatibility with Other Operating Systems</b>"
+msgstr "<b>Совместимость с другими операционными системами</b>"
+
+#: rapid/glade3/rapid.glade.h:7
+msgid "<b>Download Folder</b>"
+msgstr "<b>Каталог сохранения</b>"
+
+#: rapid/glade3/rapid.glade.h:8
+msgid "<b>Download Subfolders</b>"
+msgstr "<b>Подкаталоги сохранения</b>"
+
+#: rapid/glade3/rapid.glade.h:9
+msgid "<b>Example</b>"
+msgstr "<b>Пример</b>"
+
+#: rapid/glade3/rapid.glade.h:10
+msgid "<b>Image Devices</b>"
+msgstr "<b>Носители фотографий</b>"
+
+#: rapid/glade3/rapid.glade.h:11
+msgid "<b>Image Name Conflicts</b>"
+msgstr "<b>Конфликты в названии фотографии</b>"
+
+#: rapid/glade3/rapid.glade.h:12
+msgid "<b>Image Rename</b>"
+msgstr "<b>Переименование фотографий</b>"
+
+#: rapid/glade3/rapid.glade.h:13
+msgid "<b>Missing Backup Devices</b>"
+msgstr "<b>Отсутствующие носители резервного копирования</b>"
+
+#: rapid/glade3/rapid.glade.h:14
+msgid "<b>Program Automation</b>"
+msgstr "<b>Автоматизация программы</b>"
+
+#: rapid/glade3/rapid.glade.h:15
+msgid "<b>Sequence numbers</b>"
+msgstr "<b>Последовательность чисел</b>"
+
+#: rapid/glade3/rapid.glade.h:16
+msgid "<i>/media/externaldrive/Photos</i>"
+msgstr "<i>/media/externaldrive/Photos</i>"
+
+#: rapid/glade3/rapid.glade.h:17
+msgid "<i>Example: /home/user/photos</i>"
+msgstr "<i>Пример: /home/user/photos</i>"
+
+#: rapid/glade3/rapid.glade.h:18
+msgid "<i>Example:</i>"
+msgstr "<i>Пример:</i>"
+
+#: rapid/glade3/rapid.glade.h:19
+msgid "<i>New:</i>"
+msgstr "<i>Новое название:</i>"
+
+#: rapid/glade3/rapid.glade.h:20
+msgid "<i>Original:</i>"
+msgstr "<i>Оригинальное название:</i>"
+
+#: rapid/glade3/rapid.glade.h:21
+msgid "<span weight=\"bold\" size=\"x-large\">Automation</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Автоматизация</span>"
+
+#: rapid/glade3/rapid.glade.h:22
+msgid "<span weight=\"bold\" size=\"x-large\">Backup</span>\t"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Резервное копирование</span>\t"
+
+#: rapid/glade3/rapid.glade.h:23
+msgid "<span weight=\"bold\" size=\"x-large\">Download Folder</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Каталог сохранения</span>"
+
+#: rapid/glade3/rapid.glade.h:24
+msgid "<span weight=\"bold\" size=\"x-large\">Error Handling</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Обработка ошибок</span>"
+
+#: rapid/glade3/rapid.glade.h:25
+msgid "<span weight=\"bold\" size=\"x-large\">Image Devices</span>"
+msgstr "<span weight=\"bold\" size=\"x-large\">Носители фотографий</span>"
+
+#: rapid/glade3/rapid.glade.h:26
+msgid "<span weight=\"bold\" size=\"x-large\">Image Rename</span>\t"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Переименование фотографий</span>\t"
+
+#: rapid/glade3/rapid.glade.h:27
+msgid "<span weight=\"bold\" size=\"x-large\">Rename Options</span>"
+msgstr ""
+"<span weight=\"bold\" size=\"x-large\">Параметры переименования</span>"
+
+#: rapid/glade3/rapid.glade.h:28
+msgid "Add unique identifier"
+msgstr "Добавить уникальный идентификатор"
+
+#: rapid/glade3/rapid.glade.h:29
+msgid "Automatically detect Portable Storage Devices"
+msgstr "Автоматически определять внешние съёмные носители"
+
+#: rapid/glade3/rapid.glade.h:30
+msgid "Automatically detect backup devices"
+msgstr "Автоматически определять носители для резервного копирования"
+
+#: rapid/glade3/rapid.glade.h:31
+msgid "Automatically detect image devices"
+msgstr "Автоматически определять носители, которые содержат фотографии"
+
+#: rapid/glade3/rapid.glade.h:32
+msgid "Automation"
+msgstr "Автоматизация"
+
+#: rapid/glade3/rapid.glade.h:33
+msgid "Backup"
+msgstr "Резервное копирование"
+
+#: rapid/glade3/rapid.glade.h:34
+msgid "Backup folder name:"
+msgstr "Название каталога:"
+
+#: rapid/glade3/rapid.glade.h:35
+msgid "Backup location:"
+msgstr "Местоположение резервных копий"
+
+#: rapid/glade3/rapid.glade.h:36
+msgid "Backup photos when downloading"
+msgstr "Выполнять резервное копирование фотографий при их скачивании"
+
+#: rapid/glade3/rapid.glade.h:37
+msgid ""
+"Choose the download folder. Subfolders for the downloaded photos will be "
+"automatically created in this folder using the structure specified below."
+msgstr ""
+"Выберите каталог, где будут храниться фотографии. Подкаталоги для "
+"скачиваемых фотографий будут автоматически созданы в каждом каталоге, "
+"используя структуру указанную ниже."
+
+#: rapid/glade3/rapid.glade.h:38
+msgid ""
+"Choose whether to skip downloading the image, or to add a unique indentifier."
+msgstr ""
+"Выберите пропустить ли скачивание фотографий или добавить к ней уникальный "
+"идентификатор."
+
+#: rapid/glade3/rapid.glade.h:39
+msgid "Copyright Damon Lynch 2007-09"
+msgstr "Copyright Damon Lynch 2007-09"
+
+#: rapid/glade3/rapid.glade.h:40
+msgid "Day start:"
+msgstr "Начало дня:"
+
+#: rapid/glade3/rapid.glade.h:41
+msgid "Download / Pause"
+msgstr "Скачать / Пауза"
+
+#: rapid/glade3/rapid.glade.h:42
+msgid "Download Folder"
+msgstr "Каталог сохранения"
+
+#: rapid/glade3/rapid.glade.h:43
+msgid "Download folder:"
+msgstr "Каталог сохранения:"
+
+#: rapid/glade3/rapid.glade.h:44
+msgid "Downloads today:"
+msgstr "Скачиваний сегодня:"
+
+#: rapid/glade3/rapid.glade.h:45
+msgid "Error Handling"
+msgstr "Обработка ошибок"
+
+#: rapid/glade3/rapid.glade.h:46
+msgid "Error Log"
+msgstr "Журнал ошибок"
+
+#: rapid/glade3/rapid.glade.h:47
+msgid "Exit program after completion of successful download"
+msgstr "Выйти из программы после успешного завершения скачивания фотографий"
+
+#: rapid/glade3/rapid.glade.h:48
+msgid "If you disable automatic detection, choose the exact backup location."
+msgstr ""
+"Если вы отключаете автоматическое определение, то, пожалуйста, выберите "
+"точное местоположение носителя для резервного копирования."
+
+#: rapid/glade3/rapid.glade.h:49
+msgid ""
+"If you disable automatic detection, choose the exact location of the images."
+msgstr ""
+"Если вы отключаете автоматическое определение, то, пожалуйста, выберите "
+"точное местоположение фотографий."
+
+#: rapid/glade3/rapid.glade.h:50
+msgid ""
+"If you enable automatic detection of Portable Storage Devices, the entire "
+"device will be scanned for images. On large devices, this could take some "
+"time."
+msgstr ""
+"Если вы включите автоматическое определение съёмных носителей, то будьте "
+"готовы к тому, что они будут просканированы на наличие фотографий. На "
+"носителях большого объёма это может занять достаточно много времени."
+
+#: rapid/glade3/rapid.glade.h:51
+msgid "Ignore"
+msgstr "Игнорировать"
+
+#: rapid/glade3/rapid.glade.h:52
+msgid "Image Devices"
+msgstr "Носители фотографий"
+
+#: rapid/glade3/rapid.glade.h:53
+msgid "Image Rename"
+msgstr "Переименование фотографий"
+
+#: rapid/glade3/rapid.glade.h:54
+msgid ""
+"Image devices are devices from which to download photos, such as cameras, "
+"memory cards or Portable Storage Devices.\n"
+"\n"
+"You can download photos from multiple image devices simultaneously.\n"
+"\n"
+"<i>If downloading directly from your camera works poorly or not at all, try "
+"setting it to PTP mode. If that is not possible, consider using a card "
+"reader.</i>"
+msgstr ""
+"Носители фотографий - это устройства с которых необходимо скачать "
+"фотографии, например фотоаппараты, карты памяти или съёмные носители. \n"
+"\n"
+"Вы можете одновременно скачивать фотографии с нескольких носителей.\n"
+"\n"
+"<i>Скачивание непосредственно из фотоаппарата может работать медленно или не "
+"работать совсем, в этом случае попытайтесь установить его в режим PTP. Если "
+"это не возможно, то попробуйте использовать устройство для чтения карт "
+"памяти.</i>"
+
+#: rapid/glade3/rapid.glade.h:59
+msgid "Image location:"
+msgstr "Местоположение фотографий:"
+
+#: rapid/glade3/rapid.glade.h:60
+msgid "Import your images efficiently and reliably"
+msgstr "Эффективное и надёжное импортирование ваших фотографий"
+
+#: rapid/glade3/rapid.glade.h:61
+msgid "Overwrite"
+msgstr "Перезаписать"
+
+#: rapid/glade3/rapid.glade.h:62
+msgid "Preferences: Rapid Photo Downloader"
+msgstr "Параметры: Rapid Photo Downloader"
+
+#: rapid/glade3/rapid.glade.h:64
+msgid ""
+"Rapid Photo Downloader is free software; you can redistribute it and/or "
+"modify it under the terms of the GNU General Public License as published by "
+"the Free Software Foundation; either version 2 of the License, or (at your "
+"option) any later version.\n"
+"\n"
+"Rapid Photo Downloader is distributed in the hope that it will be useful, "
+"but WITHOUT ANY WARRANTY; without even the implied warranty of "
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General "
+"Public License for more details.\n"
+"\n"
+"You should have received a copy of the GNU General Public License along with "
+"Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., "
+"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA."
+msgstr ""
+"Rapid Photo Downloader - это бесплатное программное обеспечение; вы можете "
+"передавать его и/или модифицировать в соответствии с соглашением GNU General "
+"Public License опубликованным Free Software Foundation версии 2 или (по "
+"вашему выбору) более поздней версии.\n"
+"\n"
+"Rapid Photo Downloader распространяется с верой в то, что эта программа "
+"будет полезна вам, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ и даже без гарантий "
+"КОММЕРЧЕСКОЙ ЦЕННОСТИ или ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ КАКОГО-ЛИБО ОПРЕДЕЛЁННОГО "
+"ИСПОЛЬЗОВАНИЯ. Для дополнительной информации читайте GNU General Public "
+"License.\n"
+"\n"
+"Вы должны были получить копию GNU General Public License вместе с Rapid "
+"Photo Downloader; если вы не получили её, то вы можете написать в Free "
+"Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-"
+"1301, USA."
+
+#: rapid/glade3/rapid.glade.h:69
+msgid "Rename Options"
+msgstr "Параметры переименования"
+
+#: rapid/glade3/rapid.glade.h:70
+msgid "Report a warning"
+msgstr "Предупредить"
+
+#: rapid/glade3/rapid.glade.h:71
+msgid "Report an error"
+msgstr "Сообщить об ошибке"
+
+#: rapid/glade3/rapid.glade.h:72
+msgid "Skip"
+msgstr "Пропустить"
+
+#: rapid/glade3/rapid.glade.h:73
+msgid "Skip download"
+msgstr "Пропустить скачивание"
+
+#: rapid/glade3/rapid.glade.h:74
+msgid ""
+"Specify the folder in which backups are stored on the device. \n"
+"\n"
+"<i>Note: this will also be used to determine whether or not the device is "
+"used for backups. For each device you wish to use for backing up to, create "
+"a folder in it with this name.</i>"
+msgstr ""
+"Укажите каталог для хранения резервных копий фотографий на устройстве.\n"
+"\n"
+"<i>Примечание: На каждом носителе, который вы хотите использовать для "
+"резервного копирования, создайте каталог с этим названием.</i>"
+
+#: rapid/glade3/rapid.glade.h:77
+msgid ""
+"Specify the time in 24 hour format at which the <i>Downloads today</i> "
+"sequence number should be reset."
+msgstr ""
+"Укажите время в 24 часовом формате, в которое будет сброшена "
+"последовательность номеров параметра <i>Скачиваний сегодня</i>."
+
+#: rapid/glade3/rapid.glade.h:78
+msgid ""
+"Specify what to do when an image of the same name has already been "
+"downloaded or backed up."
+msgstr ""
+"Укажите, как следует поступить с фотографией, имеющей точно такое же "
+"название и уже скачанной или сохранённой в резервной копии."
+
+#: rapid/glade3/rapid.glade.h:79
+msgid "Specify what to do when there are no backup devices."
+msgstr ""
+"Укажите, что делать если не обнаружены носители для резервного копирования."
+
+#: rapid/glade3/rapid.glade.h:80
+msgid ""
+"Specify whether image and folder names should have any characters removed "
+"that are not allowed by other operating systems."
+msgstr ""
+"Укажите, должны ли удаляться символы в наименованиях фотографий и каталогов, "
+"которые не распознаются в других операционных системах."
+
+#: rapid/glade3/rapid.glade.h:81
+msgid "Start downloading at program startup"
+msgstr "Начать скачивание фотографий сразу после запуска программы"
+
+#: rapid/glade3/rapid.glade.h:82
+msgid "Start downloading upon image device insertion"
+msgstr "Начать скачивание фотографий при вставке носителя"
+
+#: rapid/glade3/rapid.glade.h:83
+msgid "Stored number:"
+msgstr "Сохранение под номером:"
+
+#: rapid/glade3/rapid.glade.h:84
+msgid "Strip incompatible characters"
+msgstr "Убрать несовместимые символы"
+
+#: rapid/glade3/rapid.glade.h:85
+msgid "Unmount (\"eject\") image device upon download completion"
+msgstr ""
+"Отсоединить (\"извлечь\") носитель с фотографиями после завершения скачивания"
+
+#: rapid/glade3/rapid.glade.h:86
+msgid ""
+"When backing up, choose whether to overwrite an image on the backup device "
+"that has the same name, or skip backing it up."
+msgstr ""
+"Во время резервного копирования могут встретиться фотографии с одинаковыми "
+"именами. Выберите, перезаписать ли такую фотографию или пропустить её."
+
+#: rapid/glade3/rapid.glade.h:87
+msgid ""
+"You can have your photos backed up to multiple locations as they are "
+"downloaded, e.g. external hard drives."
+msgstr ""
+"Вы можете производить резервное копирование фотографий на различные "
+"носители, в том числе на внешние жёсткие диски."
+
+#: rapid/glade3/rapid.glade.h:88
+msgid "_Clear Completed Downloads"
+msgstr "_Очистить завершённые скачивания"
+
+#: rapid/glade3/rapid.glade.h:89
+msgid "_Error Log"
+msgstr "_Журнал ошибок"
+
+#: rapid/glade3/rapid.glade.h:90
+msgid "_Get Help Online..."
+msgstr "_Получить помощь в интернете..."
+
+#: rapid/glade3/rapid.glade.h:91
+msgid "_Help"
+msgstr "_Помощь"
+
+#: rapid/glade3/rapid.glade.h:92
+msgid "_Make a Donation..."
+msgstr "_Сделать пожервование"
+
+#: rapid/glade3/rapid.glade.h:93
+msgid "_Photos"
+msgstr "_Фотографии"
+
+#: rapid/glade3/rapid.glade.h:94
+msgid "_Report a Problem..."
+msgstr "_Сообщить о проблеме..."
+
+#: rapid/glade3/rapid.glade.h:95
+msgid "_Thumbnails"
+msgstr "_Предпросмотр фотографий"
+
+#: rapid/glade3/rapid.glade.h:96
+msgid "_Translate this Application..."
+msgstr "_Перевести это приложение..."
+
+#: rapid/glade3/rapid.glade.h:97
+msgid "_View"
+msgstr "_Просмотр"
+
+#: rapid/glade3/rapid.glade.h:98
+msgid "translators please ignore this"
+msgstr ""
diff --git a/rapid-photo-downloader b/rapid-photo-downloader
new file mode 100755
index 0000000..87e63c0
--- /dev/null
+++ b/rapid-photo-downloader
@@ -0,0 +1,5 @@
+#!/usr/bin/python
+
+import rapid.rapid
+
+rapid.rapid.start ()
diff --git a/rapid/AUTHORS b/rapid/AUTHORS
new file mode 100644
index 0000000..c89d793
--- /dev/null
+++ b/rapid/AUTHORS
@@ -0,0 +1 @@
+Damon Lynch <damonlynch@gmail.com>
diff --git a/rapid/COPYING b/rapid/COPYING
new file mode 100644
index 0000000..d511905
--- /dev/null
+++ b/rapid/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/rapid/ChangeLog b/rapid/ChangeLog
new file mode 100644
index 0000000..430aab8
--- /dev/null
+++ b/rapid/ChangeLog
@@ -0,0 +1,393 @@
+Version 0.0.10
+--------------
+
+2009-06-05
+
+Updated Russian translation by Sergei Sedov.
+
+Fixed bug #383028: program would crash when using an automatically configured
+backup device and gvfs.
+
+
+
+Version 0.0.9
+-------------
+
+2009-06-02
+
+Added Italian translation by Marco Solari and Luca Reverberi.
+
+Added German translation by Martin Egger and Daniel Passler.
+
+Added Russian translation by Sergei Sedov.
+
+Added Finnish translation by Mikko Ruohola.
+
+A Help button has been added to Preferences dialog window. Clicking it takes you
+to the documentation found online at the program's website. This documentation
+is now complete.
+
+The Preferences Dialog Window is now navigated using a list control, as it was
+in early versions of the program. This change was necesseary because with some
+translations, the dialog window was becoming too wide with the normal tab
+layout. Usability of the preferences dialog is improved: it will now resize
+itself based on its content.
+
+Better integration with Nautilus is now possible through the setting of
+MimeType=x-content/image-dcf in the program's .desktop file.
+
+
+
+Version 0.0.9 beta 4
+--------------------
+
+2009-05-26
+
+Added Spanish translation by Jose Luis Navarro and Abel O'Rian.
+
+Whenever subfolder preferences are modified in the Preferences Dialog window,
+they are now checked to see if they contain any extraneous entries. If
+necessary, any entries like this are removed when the dialog window is closed.
+
+Bug fix: Changes in preferences should be applied to devices that have already
+been scanned, but their images not yet downloaded. This bug was introduced in
+beta 2 when fixing bug #368098.
+
+Bug fix: check subfolder preferences for validity before beginning download.
+While image rename preferences were checked, this check was neglected.
+
+Bug fix: do not allow automatic downloading when there is an error in the
+preferences.
+
+
+
+Version 0.0.9 beta 3
+--------------------
+
+2009-05-25
+
+Added command line options for controlling verbosity, displaying which image
+file types are recognized, and printing the program version.
+
+Updated man page to reflect recent program changes and new command line options.
+
+Prepared program for translation into other languages. Thanks go to Mark Mruss
+and his blog http://www.learningpython.com for code examples and explanations.
+
+Polish translation by Michal Predotka. Coming soon: French, German and
+Spanish translations.
+
+To install the program using python setup.py, the program msgfmt must now be
+present. On most Linux distributions, this is found in the package gettext.
+
+Updated INSTALL file to reflect minimum version of pyexiv2 needed, and included
+information about handling any error related to msgfmt not being installed.
+
+Minor fixes to logic that checks whether the Download button should be disabled
+or not. This should now be more reliable.
+
+Bug fix: error log window can now be reopened after being closed with the "x"
+button. Thanks go to ESR and his Python FAQ entry for this fix.
+
+Bug fix: example of subfolder name now has word wrap. Thanks go to Michal
+Predotka for reporting this.
+
+Bug fix: don't crash when a thumbnail image is missing and the 'orientation'
+variable has not yet been assigned.
+
+
+
+Version 0.0.9 beta 2
+--------------------
+
+2009-05-12
+
+By popular demand, allow direct downloading from cameras. This support is
+experimental and may not work with your camera. This is possible through the use
+of the new gvfs service, provided by GIO, that exists in recent versions of
+Linux. A recent version of Linux is a must. The camera must also be supported by
+libgphoto2 in combination with gvfs. If you cannot browse the camera's contents
+in a file manager (e.g. Nautilus), the camera download will not work until the
+gvfs support is improved.
+
+Although this is a popular request, the reality is that downloading images
+directly from the camera is often extremely slow in comparison to popping the
+memory card into a card reader and downloading from that.
+
+Fix bug #368098: the program now starts more quickly and does not become
+unresponsive when scanning devices with a large number of images. This will
+hardly be noticeable by users that download from memory cards, but for those
+who download from hard drives with hundreds of GBs of files -- they'll notice
+a big difference.
+
+Fix bug #372284: for image renaming, the "image number" component is more
+robust. Now, only the series of digits at the end of a filename are recognized
+as the image number (obviously the file's extension is not included as being
+part of the filename in this case). This allows takes in account files from
+cameras like the Canon 1D series, which can have filenames like VD1D7574.CR2.
+
+Bug fix: don't download from volumes mounted while the program is already
+running unless auto detection is specified. This bug could occur when auto
+detection was enabled, then disabled, and then a volume was mounted.
+
+
+
+Version 0.0.8
+-------------
+
+2009-05-01
+
+Added stored and downloads today sequence numbers:
+
+* The stored sequence number is remembered each time the program is run.
+
+* Downloads today tracks how many downloads are made on a given day. The time a
+ day "starts" is set via a new preference value, day start. This is useful if
+ you often photograph something late at night (e.g. concerts) and want a new
+ day to "start" at 3am, for instance.
+
+Make estimate of time remaining to download images much more accurate.
+
+Display download speed in status bar.
+
+Reorganized sequence number/letter selection in preferences.
+
+Add feature to detect change in program version, upgrading preferences where
+necessary.
+
+Only allow one instance of the program to be run -- raise existing window if it
+is run again. This is very useful when Rapid Photo Downloader is set to run
+automatically upon insertion of a memory card.
+
+Add "exit at end of successful download" automation feature.
+
+When an image's download is skipped, the thumbnail is now lightened.
+
+Show a missing image icon if the thumbnail cannot be displayed for some reason.
+(See bug #369640 for why thumbnail images from certain RAW files are not
+displayed).
+
+Resize main window when an image device is inserted -- it now expands to show
+each device that is inserted.
+
+Do not proceed with download if there is an error in the image rename or
+download subfolder preferences. Instead, indicate a download error.
+
+Allow version 0.1.1 of pyexiv2 to be used (an older version of the library code
+that is used to get information on the images, found in distributions like
+Ubuntu 8.04 Hardy Heron).
+
+In cases where image rename or download subfolder preferences are invalid,
+more helpful information is printed to the console output.
+
+Bug fix: better handle automated shortening Canon names like 'Canon 5D Mark II'.
+It is now shortened to '5DMkII' instead of merely '5D'.
+
+Bug fix: reenable example of image renaming and subfolder name generation by
+using first image from the first available download device. This was
+inadvertently disabled in an earlier beta.
+
+Bug fix: make default download subfolder YYYY/YYYYMMDD again. It was
+inadvertently set to DDMMYYYY/YYYYMMDD in beta 6.
+
+Bug fix: don't change download button label to "pause" when "Start downloading
+on program startup" is set to true.
+
+Bug fix: implement code to warn / give error about missing backup devices.
+
+Bug fix: reset progress bar after completion of successful download.
+
+Fix bug #317404 when clearing completed downloads.
+
+
+
+Version 0.0.8 beta 7
+--------------------
+
+2009-04-07
+
+Added serial number metadata option for select Nikon, Canon, Olympus, Fuji,
+Panasonic, and Kodak cameras.
+
+Added shutter count metadata option for select Nikon cameras, e.g. Nikon D300,
+D3 etc.
+
+Add owner name metadata option for select Canon cameras, e.g. 5D Mk II etc.
+
+
+Version 0.0.8 beta 6
+--------------------
+
+2009-03-31
+
+Add YYYY-MM-DD and YY-MM-DD options in date time renaming, suggested by
+Andreas F.X. Siegert and Paul Gear.
+
+Fix bug #352242 where image has no metadata.
+
+Handle images with corrupt metadata more gracefully.
+
+
+Version 0.0.8 beta 5
+--------------------
+
+2009-03-30
+
+Reduce console output.
+
+
+Version 0.0.8 beta 4
+--------------------
+
+2009-03-25
+
+Updated Ubuntu package.
+
+Version 0.0.8 beta 3
+--------------------
+
+2009-03-25
+
+Updated Ubuntu package.
+
+
+Version 0.0.8 beta 2
+--------------------
+
+2009-03-25
+
+First Ububtu package.
+
+Rename tarball package to suit package name.
+
+Updated README.
+
+Version 0.0.8 beta 1
+--------------------
+
+2009-03-20
+
+Make file renaming thread safe, fixing a long-standing (if difficult to
+activate) bug.
+
+Implement add unique identifier when file name is not unique.
+
+Added "Report a Problem", "Get Help Online", "Make a Donation" to Help menu.
+
+Implemented "Clear completed downloads" menu item.
+
+Download images in order they were taken (checked by time they modified).
+
+Fixed bug where choosing text as the first item in a download subfolder caused a
+crash.
+
+Fixed bug where date and time choices based on when image is downloaded caused a
+crash.
+
+Initial code to show error message when image renaming preferences have an
+error.
+
+Fixed bug where some invalid preferences were not being caught.
+
+Run default python, not one specified in env, as per recommendations in Debian
+Python Policy.
+
+Remove initial period from filename extension when generating a subfolder name
+(or else the folder will be hidden).
+
+Check to see if metadata is essential to generate image names is now more
+robust.
+
+Remove list control from preferences, reverting to normal tabbed preferences,
+as the window was becoming too wide.
+
+Show notifcations via libnotify.
+
+Error and warning icons can now be clicked on to open log window.
+
+Finally, last but certainly not least--implemented sequence number and sequence
+letter generation:
+ * session sequence number
+ * sequence letter
+Coming soon:
+ * downloads today sequence number
+ * subfolder sequence number
+ * stored sequence number
+
+
+Version 0.0.7
+-------------
+
+2009-01-13
+
+Implemented option for automatic detection of Portal Storage Devices.
+
+Version 0.0.6
+-------------
+
+2009-01-11
+
+Fixed extremely annoying bug where memory cards could not be unmounted.
+
+Made sample image selection for preferences more robust.
+
+Added license details to about dialog.
+
+Fix bug where image rename preferences entry boxes vertically expanded, looking
+very ugly indeed.
+
+Wrap new filename in image rename preferences when it becomes too long.
+
+Make default download folder selection more robust.
+
+Remove sequence number and sequence letter from list of choices for image rename
+(not yet implemented).
+
+Bug #314825: fix by not calling gnomevfs.get_local_path_from_uri() unless
+strictly necessary.
+
+Version 0.0.5
+-------------
+
+2009-01-09
+
+Implement auto download on device insertion, and auto download on program
+startup.
+
+Increase default width of preferences dialog box.
+
+Add vertical scrollbar to image rename preferences.
+
+Fixes for bugs #313463 & #313462.
+
+Version 0.0.4
+-------------
+
+2009-01-06
+
+Bug #314284: Implement backup functionality.
+
+Bug #314285: Insert debugging code to help determine the cause of this bug.
+
+Version 0.0.3
+-------------
+
+2009-01-03
+
+Bug #313398: Fix bug where application needed to be restarted for new
+preferences to take effect.
+
+Added setup.py installer.
+
+Version 0.0.2
+-------------
+
+Dependencies:
+Pyexiv 0.1.2
+
+Updated metadata code to reflect changes in pyexiv library.
+
+Version 0.0.1
+-------------
+
+Initial release.
diff --git a/rapid/INSTALL b/rapid/INSTALL
new file mode 100644
index 0000000..27f9b07
--- /dev/null
+++ b/rapid/INSTALL
@@ -0,0 +1,36 @@
+Rapid Photo Downloader depends on the following software:
+
+- GNOME 2.18
+- GTK+ 2.10
+- Python 2.5
+- pygtk 2.10
+- python-gconf 2.18
+- python-glade2 2.10
+- gnome-python 2.10
+- libexiv2 0.15
+- pyexiv2 0.1.1
+
+To run Rapid Photo Downloader you will need all the software mentioned above. To
+start from a fairly basic system, I suggest the following:
+
+1. Install the required gnome packages from your linux distribution's package
+ repositories. On a recent linux distribution, expect all to be available for
+ easy download and installation. If you already use gnome, most of the
+ packages will already be installed. Do confirm that python-gconf,
+ python-glade2, and gnome-python are installed, because they
+ may not be quite so common in a base system.
+
+2. Install pyexiv2. You can probably do that using your distributions's package
+ repositories (look for python-pyexiv2). But if not, there are instructions
+ here:
+
+ http://tilloy.net/dev/pyexiv2/developers.htm
+
+3. Install this application from the tarball. You probably need to be the
+ super user (root) to be able to do this:
+
+ sudo python setup.py install
+
+ If you get an error saying 'Error while running msgfmt', you will need to
+ install the gettext package on your system, which contains the msgfmt
+ program.
diff --git a/rapid/TODO b/rapid/TODO
new file mode 100644
index 0000000..5465850
--- /dev/null
+++ b/rapid/TODO
@@ -0,0 +1,26 @@
+For major release (0.10.0):
+===========================
+
+* sequencing:
+ - allow generation of unique sequences based on date time for last 1 - n days, via menu
+
+* download profiles (combinations of subfolder and image renaming preferences)
+* better handle preference changes while downloads are occurring
+* handle unexpected media removal, disk full, all kinds of write errors
+* indicate different levels of error better in log window
+* sum amount of images to be downloaded, and how much free space on the file system
+* check download locations and sources still valid when starting the application
+* rework checkPrefsForValidity() to account for multiple subfolder problems
+
+For future releases:
+====================
+
+* Better application icon -- help needed!
+* Get more metadata
+ - lens
+* User defined camera model mapping
+* Job codes
+* use python's high performance deque to improve idletube
+
+
+
diff --git a/rapid/ValidatedEntry.py b/rapid/ValidatedEntry.py
new file mode 100644
index 0000000..cb453f4
--- /dev/null
+++ b/rapid/ValidatedEntry.py
@@ -0,0 +1,383 @@
+# Copyright (c) 2006, Daniel J. Popowich
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# Send bug reports and contributions to:
+#
+# dpopowich AT astro dot umass dot edu
+#
+
+'''
+ValidatedEntry.py
+
+Provides ValidatedEntry, a subclass of gtk.Entry which validates
+input.
+
+Usage: create an instance of ValidatedEntry, specifying the function
+to validate input. E.g.:
+
+ : def money(text):
+ : "validate input to be monetary value"
+ : ...
+ :
+ : money_entry = ValidatedEntry(money)
+
+Validation functions must accept one argument, the text to be
+validated, and must return one of:
+
+ 1: the input is valid.
+ 0: the input is invalid and should not be displayed.
+ -1: the input is partially valid and will be displayed (and by
+ default with a different background color).
+
+Three module-level variables are defined for the convenience of
+validation function writers: VALID (1), INVALID (0), PARTIAL (-1).
+
+There is one public method, isvalid(), which will return True if the
+current text is valid.
+
+Note: care should be taken when implementing validation functions to
+allow empty strings to be VALID or at least PARTIAL. An empty string
+should never be INVALID.
+
+Note: the hooks for calling the validation function are implemented by
+connecting the object to handlers for the gtk.Editable "insert-text"
+and "delete-text" signals. These handlers are connected to instances
+in the constructor, so will, by default, be called before other
+handlers connected to the widgets for "*-text" signals. When input is
+INVALID, stop_emission() is called, so later handlers for "*-text"
+signals will not be called.
+
+See the doc string for ValidatedEntry.__init__ for more details.
+
+'''
+
+import pygtk
+pygtk.require('2.0')
+
+import gtk
+import gtk.gdk
+
+if gtk.gtk_version < (2, 8):
+ import warnings
+
+ msg ='''This module was developed and tested with version 2.8.9 of gtk.
+You are using version %d.%d.%d. Your milage may vary''' % gtk.gtk_version
+ warnings.warn(msg)
+
+# major, minor, patch
+version = 1, 0, 4
+
+PARTIAL, INVALID, VALID = range(-1,2)
+
+class ValidatedEntry(gtk.Entry):
+
+ white = gtk.gdk.color_parse('white')
+ yellow = gtk.gdk.color_parse('yellow')
+
+ def __init__(self, valid_func,
+ max=0,
+ use_bg=True, valid_bg=white, partial_bg=yellow,
+ error_func=None):
+ '''
+ Create instance of validating gtk.Entry.
+
+ valid_func: the function to validate input. See module doc
+ string for details.
+
+ max: passed to gtk.Entry constructor. (default: 0)
+
+ use_bg: if True (the default) set the base color of the
+ widget to indicate validity; see valid_bg and partial_bg.
+
+ valid_bg: a gtk.gdk.Color; the base color of the widget when
+ the input is valid. (default: white)
+
+ partial_bg: a gtk.gdk.Color; the base color of the widget when
+ the input is partially valid. (default: yellow)
+
+ error_func: a function to call (with no arguments) when
+ valid_func returns INVALID. If None (the default)
+ the default action will be to emit a short beep.
+ '''
+
+ assert valid_func('') != INVALID, 'valid_func cannot return INVALID for an empty string'
+
+ gtk.Entry.__init__(self, max)
+
+ self.__valid_func = valid_func
+ self.__use_bg = use_bg
+ self.__valid_bg = valid_bg
+ self.__partial_bg = partial_bg
+ self.__error_func = (error_func or
+ gtk.gdk.display_get_default().beep)
+
+ self.connect('insert-text', self.__insert_text_cb)
+ self.connect('delete-text', self.__delete_text_cb)
+
+ # bootstrap with an empty string (so the box will appear with
+ # the partial_bg if an empty string is PARTIAL)
+ self.insert_text('')
+
+ def isvalid(self):
+ return self.__isvalid
+
+ def __insert_text_cb(self, entry, text, length, position):
+ 'callback for "insert-text" signal'
+
+ # generate what the new text will be
+ text = text[:length]
+ pos = self.get_position()
+ old = self.get_text()
+ new = old[:pos] + text + old[pos:]
+
+ # validate the new text
+ self.__validate(new, 'insert-text')
+
+ def __delete_text_cb(self, entry, start, end):
+ 'callback for "delete-text" signal'
+
+ # generate what the new text will be
+ old = self.get_text()
+ new = old[:start] + old[end:]
+
+ # validate the new text
+ self.__validate(new, 'delete-text')
+
+ def __validate(self, text, signal):
+ 'calls the user-provided validation function'
+
+ # validate
+ r = self.__valid_func(text)
+ if r == VALID:
+ self.__isvalid = True
+ if self.__use_bg:
+ self.modify_base(gtk.STATE_NORMAL, self.__valid_bg)
+ elif r == PARTIAL:
+ self.__isvalid = False
+ if self.__use_bg:
+ self.modify_base(gtk.STATE_NORMAL, self.__partial_bg)
+ else:
+ # don't set self.__isvalid: since we're not displaying the
+ # new value, the validity should be whatever it was before
+ self.stop_emission(signal)
+ self.__error_func()
+
+
+######################################################################
+#
+# Sample validation functions to use with ValidatedEntry
+#
+######################################################################
+
+import re
+
+
+# STRING (non-empty after stripping)
+def v_nonemptystring(value):
+ '''
+ VALID: non-empty string after stripping whitespace
+ PARTAL: empty or all whitespace
+ INVALID: N/A
+ '''
+ if value.strip():
+ return VALID
+ return PARTIAL
+
+# INT
+def v_int(value):
+ '''
+ VALID: any postive or negative integer
+ PARTAL: empty or leading "-"
+ INVALID: non-numeral
+ '''
+ v = value.strip()
+ if not v or v == '-':
+ return PARTIAL
+ try:
+ int(value)
+ return VALID
+ except:
+ return INVALID
+
+# FLOAT
+def v_float(value):
+ '''
+ VALID: any postive or negative floating point
+ PARTAL: empty or leading "-", "."
+ INVALID: non-numeral
+ '''
+ v = value.strip()
+ if not v or v in ('-', '.', '-.'):
+ return PARTIAL
+ try:
+ float(value)
+ return VALID
+ except:
+ return INVALID
+
+
+# ISBN
+_isbnpartial = re.compile('[0-9]{0,9}[0-9xX]?$')
+def v_isbn(v):
+
+ '''Validate ISBN input.
+
+ From the isbn manual, section 4.4:
+
+ The check digit is the last digit of an ISBN. It is calculated on
+ a modulus 11 with weights 10-2, using X in lieu of 10 where ten
+ would occur as a check digit. This means that each of the first
+ nine digits of the ISBN -- excluding the check digit itself -- is
+ multiplied by a number ranging from 10 to 2 and that the resulting
+ sum of the products, plus the check digit, must be divisible by 11
+ without a remainder.'''
+
+
+ if _isbnpartial.match(v):
+ # isbn is ten characters in length
+ if len(v) < 10:
+ return PARTIAL
+
+ s = 0
+
+ for i, c in enumerate(v):
+ s += (c in 'xX' and 10 or int(c)) * (10 - i)
+
+ if s % 11 == 0:
+ return VALID
+
+ return INVALID
+
+# MONEY
+# re for (possibly negative) money
+_money_re = re.compile('-?\d*(\.\d{1,2})?$')
+# validation function for money
+def v_money(value):
+ '''
+ VALID: any postive or negative floating point with at most two
+ digits after the decimal point.
+ PARTAL: empty or leading "-", "."
+ INVALID: non-numeral or more than two digits after the decimal
+ point.
+ '''
+ if not value or value == '-' or value[-1] == '.':
+ return PARTIAL
+
+ if _money_re.match(value):
+ return VALID
+
+ return INVALID
+
+# PHONE
+# the characters in a phone number
+_phonechars = re.compile('[- 0-9]*$')
+# valid phone number: [AC +]EXT-LINE
+_phone = re.compile('([2-9][0-8][0-9]\s+)?[2-9][0-9]{2}-[0-9]{4}$')
+def v_phone(value):
+ '''
+ VALID: any phone number of the form: EXT-LINE -or- AC EXT-LINE.
+ PARTAL: any characters that make up a valid #.
+ INVALID: characters that are not used in a phone #.
+ '''
+ if _phone.match(value):
+ return VALID
+ if _phonechars.match(value):
+ return PARTIAL
+ return INVALID
+
+def empty_valid(vfunc):
+
+ '''
+ empty_valid is a factory function returning a validation function.
+ All of the validation functions in this module return PARTIAL for
+ empty strings which, in effect, forces non-empty input. There may
+ be a case where, e.g., you want money input to be optional, but
+ v_money will not consider empty input VALID. Instead of writing
+ another validation function you can instead use empty_valid(). By
+ wrapping a validation function with empty_valid(), input (after
+ stripping), if empty, will be considered VALID. E.g.:
+
+ ventry = ValidatedEntry(empty_valid(v_money))
+
+ It is recommended that all your validation functions treat empty
+ input as PARTIAL, for consistency across all validation functions
+ and for use with empty_valid().
+ '''
+
+ def validate(value):
+ if not value.strip():
+ return VALID
+ return vfunc(value)
+
+ return validate
+
+
+def bounded(vfunc, conv, minv=None, maxv=None):
+
+ '''
+ bounded is a factory function returning a validation function
+ providing bounded input. E.g., you may want an entry that accepts
+ integers, but within a range, say, a score on a test graded in
+ whole numbers from 0 to 100:
+
+ score_entry = ValidatedEntry(bounded(v_int, int, 0, 100))
+
+ Arguments:
+
+ vfunc: A validation function.
+ conv: A callable that accepts a string argument (the text in
+ the entry) and returns a value to be compared to minv
+ and maxv.
+ minv: None or a value of the same type returned by conv. If
+ None, there is no minimum value enforced. If a value,
+ it will be the minimum value considered VALID.
+ maxv: None or a value of the same type returned by conv. If
+ None, there is no maximum value enforced. If a value,
+ it will be the maximum value considered VALID.
+
+ One or both of minv/maxv must be specified.
+
+ The function returned will call vfunc on entry input and if vfunc
+ returns VALID, the input will be converted by conv and compared to
+ minv/maxv. If the converted value is within the bounds of
+ minv/maxv then VALID will be returned, else PARTIAL will be
+ returned.
+
+ '''
+
+ assert minv is not None or maxv is not None, \
+ 'One of minv/maxv must be specified'
+
+ def F(value):
+
+ r = vfunc(value)
+ if r == VALID:
+ v = conv(value)
+ if minv is not None and v < minv:
+ return PARTIAL
+ if maxv is not None and v > maxv:
+ return PARTIAL
+ return r
+
+ return F
+
+
diff --git a/rapid/__init__.py b/rapid/__init__.py
new file mode 100644
index 0000000..792d600
--- /dev/null
+++ b/rapid/__init__.py
@@ -0,0 +1 @@
+#
diff --git a/rapid/common.py b/rapid/common.py
new file mode 100644
index 0000000..d687049
--- /dev/null
+++ b/rapid/common.py
@@ -0,0 +1,181 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007-09 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+import sys
+import gc
+import distutils.version
+import gtk.gdk as gdk
+
+import config
+
+import locale
+import gettext
+
+class Configi18n:
+ """ Setup translation
+
+ Adapated from code example of Mark Mruss http://www.learningpython.com.
+ Unlike his example, this code uses a local locale directory only if the environment
+ variable LOCALEDIR has been set to some or other value.
+ """
+
+ # Do not put this code block in __init__, because it needs to be run only once
+
+ # if the evironment value 'LOCAELDIR' is set, then use this as the source of translation data
+ # otherwise, rely on the system-wide data
+ locale_path = os.environ.get('LOCALEDIR', None)
+
+ # Init the list of languages to support
+ langs = []
+ #Check the default locale
+ lc, encoding = locale.getdefaultlocale()
+ if (lc):
+ #If we have a default, it's the first in the list
+ langs = [lc]
+ # Now let's get all of the supported languages on the system
+ language = os.environ.get('LANGUAGE', None)
+ if (language):
+ # langage comes back something like en_CA:en_US:en_GB:en
+ langs += language.split(":")
+
+ # add on to the back of the list the translations that we know that we have, our defaults
+ langs += ["en_US"]
+
+ # Now langs is a list of all of the languages that we are going
+ # to try to use. First we check the default, then what the system
+ # told us, and finally the 'known' list
+
+ gettext.bindtextdomain(config.APP_NAME, locale_path)
+ gettext.textdomain(config.APP_NAME)
+ # Get the language to use
+ lang = gettext.translation(config.APP_NAME, locale_path, languages=langs, fallback = True)
+ # Install the language, map _() (which we marked our
+ # strings to translate with) to self.lang.gettext() which will
+ # translate them.
+ _ = lang.gettext
+
+
+def pythonifyVersion(v):
+ """ makes version number a version number in distutils sense"""
+ return distutils.version.StrictVersion(v.replace( '~',''))
+
+def getFullProgramName():
+ """ return the full name of the process running """
+ return os.path.basename(sys.argv[0])
+
+def getProgramName():
+ """ return the name of the process running, removing the .py extension if it exists """
+ programName = getFullProgramName()
+ if programName.find('.py') > 0:
+ programName = programName[:programName.find('.py')]
+ return programName
+
+def splitDirectories(directories):
+ """ split directories specified in string into a list """
+ if directories.find(',') > 0:
+ d = directories.split(',')
+ else:
+ d = directories.split()
+ directories = []
+ for i in d:
+ directories.append(i.strip())
+ return directories
+
+
+
+def getFullPath(path):
+ """ make path relative to home directory if not an absolute path """
+ if os.path.isabs(path):
+ return path
+ else:
+ return os.path.join(os.path.expanduser('~'), path)
+
+
+def escape(s):
+ """
+ Replace special characters by SGML entities.
+ """
+ entities = ("&&amp;", "<&lt;", ">&gt;")
+ for e in entities:
+ s = s.replace(e[0], e[1:])
+ return s
+
+def formatSizeForUser(bytes, zeroString="", withDecimals=True, kbOnly=False):
+ """Format an int containing the number of bytes into a string suitable for
+ printing out to the user. zeroString is the string to use if bytes == 0.
+ source: https://develop.participatoryculture.org/trac/democracy/browser/trunk/tv/portable/util.py?rev=3993
+
+ """
+ if bytes > (1 << 30) and not kbOnly:
+ value = (bytes / (1024.0 * 1024.0 * 1024.0))
+ if withDecimals:
+ format = "%1.1fGB"
+ else:
+ format = "%dGB"
+ elif bytes > (1 << 20) and not kbOnly:
+ value = (bytes / (1024.0 * 1024.0))
+ if withDecimals:
+ format = "%1.1fMB"
+ else:
+ format = "%dMB"
+ elif bytes > (1 << 10):
+ value = (bytes / 1024.0)
+ if withDecimals:
+ format = "%1.1fKB"
+ else:
+ format = "%dKB"
+ elif bytes > 1:
+ value = bytes
+ if withDecimals:
+ format = "%1.1fB"
+ else:
+ format = "%dB"
+ else:
+ return zeroString
+ return format % value
+
+def scale2pixbuf(width_max, height_max, pixbuf, return_size=False):
+ """
+ Scale to width_max and height_max.
+ Keep aspect ratio.
+ Code adapted from gthumpy, by guettli
+ """
+
+ width_orig = float(pixbuf.get_width())
+ height_orig = float(pixbuf.get_height())
+ if (width_orig / width_max) > (height_orig / height_max):
+ height = int((height_orig / width_orig) * width_max)
+ width = width_max
+ else:
+ width = int((width_orig / height_orig) * height_max)
+ height=height_max
+
+ pixbuf = pixbuf.scale_simple(width, height, gdk.INTERP_BILINEAR)
+ gc.collect() # Tell Python to clean up the memory
+ if return_size:
+ return pixbuf, width_orig, height_orig
+ return pixbuf
+
+
+
+if __name__ == '__main__':
+ i = Configi18n()
+ _ = i._
+ print _("hello world")
diff --git a/rapid/config.py b/rapid/config.py
new file mode 100644
index 0000000..2e59841
--- /dev/null
+++ b/rapid/config.py
@@ -0,0 +1,58 @@
+# -*- coding: latin1 -*-
+### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+version = '0.0.10'
+
+GCONF_KEY="/apps/rapid-photo-downloader"
+GLADE_FILE = "glade3/rapid.glade"
+
+DBUS_NAME = "net.damonlynch.RapidPhotoDownloader"
+
+#i18n
+APP_NAME = "rapid-photo-downloader"
+
+MEDIA_LOCATION = "/media"
+
+SKIP_DOWNLOAD = "skip download"
+ADD_UNIQUE_IDENTIFIER = "add unique identifier"
+
+REPORT_WARNING = "warning"
+REPORT_ERROR = "error"
+IGNORE = "ignore"
+
+DEFAULT_PHOTO_LOCATIONS = ['Pictures', 'Photos']
+DEFAULT_BACKUP_LOCATION = 'Pictures'
+
+MAX_NO_READERS = 20
+
+RAW_FILE_EXTENSIONS = ['arw', 'dcr', 'cr2', 'crw', 'dng', 'mef', 'mos', 'mrw',
+ 'nef', 'orf', 'pef', 'raf', 'raw', 'sr2']
+
+#exiv2 0.18.1 introduces support for Panasonic .RW2 files
+
+NON_RAW_IMAGE_FILE_EXTENSIONS = ['jpg', 'jpe', 'jpeg', 'tif', 'tiff']
+
+CRITICAL_ERROR = 1
+SERIOUS_ERROR = 2
+WARNING = 3
+
+MAX_LENGTH_DEVICE_NAME = 15
+
+#logging - to be implemented
+#LOGFILE_DIRECTORY = '.rapidPhotoDownloader' # relative to home directory
+#MAX_LOGFILE_SIZE = 100 * 1024 # bytes
+#MAX_LOGFILES = 5
diff --git a/rapid/glade3/image-missing.svg b/rapid/glade3/image-missing.svg
new file mode 100644
index 0000000..4351feb
--- /dev/null
+++ b/rapid/glade3/image-missing.svg
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="48px" height="48px" id="svg1306" sodipodi:version="0.32" inkscape:version="0.45" sodipodi:docbase="/home/dobey/Projects/gnome-icon-theme/scalable/status" sodipodi:docname="image-missing.svg" inkscape:output_extension="org.inkscape.output.svg.inkscape">
+ <defs id="defs1308">
+ <linearGradient inkscape:collect="always" id="linearGradient6346">
+ <stop style="stop-color: rgb(85, 87, 83); stop-opacity: 1;" offset="0" id="stop6348"/>
+ <stop style="stop-color: rgb(46, 52, 54); stop-opacity: 1;" offset="1" id="stop6350"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient5060">
+ <stop style="stop-color: black; stop-opacity: 1;" offset="0" id="stop5062"/>
+ <stop style="stop-color: black; stop-opacity: 0;" offset="1" id="stop5064"/>
+ </linearGradient>
+ <linearGradient id="linearGradient5048">
+ <stop style="stop-color: black; stop-opacity: 0;" offset="0" id="stop5050"/>
+ <stop id="stop5056" offset="0.5" style="stop-color: black; stop-opacity: 1;"/>
+ <stop style="stop-color: black; stop-opacity: 0;" offset="1" id="stop5052"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient6431">
+ <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop6433"/>
+ <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop6435"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" id="linearGradient6390">
+ <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop6392"/>
+ <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop6394"/>
+ </linearGradient>
+ <linearGradient id="linearGradient6374">
+ <stop style="stop-color: rgb(85, 87, 83); stop-opacity: 1;" offset="0" id="stop6376"/>
+ <stop style="stop-color: rgb(136, 138, 133); stop-opacity: 1;" offset="1" id="stop6378"/>
+ </linearGradient>
+ <linearGradient id="linearGradient6366">
+ <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 1;" offset="0" id="stop6368"/>
+ <stop style="stop-color: rgb(255, 255, 255); stop-opacity: 0;" offset="1" id="stop6370"/>
+ </linearGradient>
+ <linearGradient id="linearGradient6327">
+ <stop style="stop-color: rgb(136, 138, 133); stop-opacity: 1;" offset="0" id="stop6329"/>
+ <stop style="stop-color: rgb(238, 238, 236); stop-opacity: 1;" offset="1" id="stop6331"/>
+ </linearGradient>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient6327" id="linearGradient6333" x1="42.999424" y1="36.811924" x2="40.621296" y2="34.433796" gradientUnits="userSpaceOnUse"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient6327" id="linearGradient6360" x1="61.18124" y1="137.97644" x2="20.420683" y2="2.6749926" gradientUnits="userSpaceOnUse"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient6366" id="linearGradient6372" x1="38.908649" y1="35.960426" x2="35.032925" y2="30.679369" gradientUnits="userSpaceOnUse"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient6374" id="radialGradient6382" cx="39.437065" cy="34.33852" fx="39.437065" fy="34.33852" r="6" gradientTransform="matrix(0.1875, -1.05343, 0.718081, 0.127811, 7.82271, 71.0304)" gradientUnits="userSpaceOnUse"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient6390" id="radialGradient6396" cx="20.236877" cy="25.043303" fx="20.236877" fy="25.043303" r="22" gradientTransform="matrix(0.940906, -0.20665, 0.109821, 0.50003, -1.55441, 13.2196)" gradientUnits="userSpaceOnUse"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient6431" id="radialGradient6437" cx="40.179535" cy="34.080399" fx="40.179535" fy="34.080399" r="4.125" gradientTransform="matrix(1, 0, 0, 0.935606, 0, 2.30711)" gradientUnits="userSpaceOnUse"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient5060" id="radialGradient6909" gradientUnits="userSpaceOnUse" gradientTransform="matrix(-0.0160648, 0, 0, 0.0741176, 11.6816, -1.17508)" cx="605.71429" cy="486.64789" fx="605.71429" fy="486.64789" r="117.14286"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient5060" id="radialGradient6912" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.104421, 0, 0, 0.0741176, -27.9305, -1.17508)" cx="605.71429" cy="486.64789" fx="605.71429" fy="486.64789" r="117.14286"/>
+ <linearGradient inkscape:collect="always" xlink:href="#linearGradient5048" id="linearGradient6915" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.0683432, 0, 0, 0.0741176, -6.20118, -1.17508)" x1="302.85715" y1="366.64789" x2="302.85715" y2="609.50507"/>
+ <radialGradient inkscape:collect="always" xlink:href="#linearGradient6346" id="radialGradient6352" cx="24.013514" cy="39.717846" fx="24.013514" fy="39.717846" r="20.013513" gradientTransform="matrix(2.00322, 0, 0, 1.45136, -24.0909, -22.3947)" gradientUnits="userSpaceOnUse"/>
+ </defs>
+ <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" inkscape:cx="50.321592" inkscape:cy="19.160509" inkscape:current-layer="layer1" showgrid="false" inkscape:grid-bbox="true" inkscape:document-units="px" fill="#fcaf3e" stroke="#555753" showguides="true" inkscape:guide-bbox="false" inkscape:window-width="895" inkscape:window-height="760" inkscape:window-x="208" inkscape:window-y="229" inkscape:showpageshadow="false" showborder="false" gridspacingx="0.5px" gridspacingy="0.5px" gridempspacing="2" inkscape:grid-points="false" gridtolerance="50" inkscape:object-paths="false"/>
+ <metadata id="metadata1311">
+ <rdf:RDF>
+ <cc:Work rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
+ <dc:title>Generic Image</dc:title>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Lapo Calamandrei</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://www.gnome.org</dc:source>
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title>Jakub Steiner, Andreas Nilsson</dc:title>
+ </cc:Agent>
+ </dc:contributor>
+ <cc:license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/"/>
+ </cc:Work>
+ <cc:License rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
+ <cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
+ <cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
+ <cc:requires rdf:resource="http://web.resource.org/cc/SourceCode"/>
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g id="layer1" inkscape:label="Layer 1" inkscape:groupmode="layer">
+ <g id="g6917">
+ <rect y="26" x="2" height="18" width="33" id="rect6057" style="overflow: visible; marker: none; opacity: 0.39196; color: rgb(0, 0, 0); fill: url(#linearGradient6915) rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline;"/>
+ <path sodipodi:nodetypes="ccscc" id="path6059" d="M 35,26.00062 C 35,26.00062 35,43.999627 35,43.999627 C 37.30962,44.01418 40.033409,43.272315 42.389531,42.027493 C 45.519106,40.37403 48.000002,37.833194 48,34.998965 C 48,30.030967 41.999197,26.000621 35,26.00062 z " style="overflow: visible; marker: none; opacity: 0.402062; color: rgb(0, 0, 0); fill: url(#radialGradient6912) rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline;"/>
+ <path style="overflow: visible; marker: none; opacity: 0.402062; color: rgb(0, 0, 0); fill: url(#radialGradient6909) rgb(0, 0, 0); fill-opacity: 1; fill-rule: nonzero; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: miter; stroke-miterlimit: 4; stroke-dasharray: none; stroke-dashoffset: 0pt; stroke-opacity: 1; visibility: visible; display: inline;" d="M 2,26.00062 C 2,26.00062 2,43.999627 2,43.999627 C 1.172704,44.03351 1.3577825e-06,39.966963 1.3577825e-06,34.998965 C 1.3577825e-06,30.030967 0.92320113,26.000621 2,26.00062 z " id="path6061" sodipodi:nodetypes="cccc"/>
+ </g>
+ <path style="fill: url(#linearGradient6360) rgb(0, 0, 0); fill-opacity: 1; stroke: rgb(136, 138, 133); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 2.767767,6.5 L 45.232237,6.5 C 45.93458,6.5 46.500004,7.0654241 46.500004,7.767767 L 46.5,30.5 C 46.5,31.202343 36.202343,40.5 35.5,40.5 L 2.767767,40.5 C 2.0654241,40.5 1.5,39.934576 1.5,39.232233 L 1.5,7.767767 C 1.5,7.0654241 2.0654241,6.5 2.767767,6.5 z " id="rect5350" sodipodi:nodetypes="ccccccccc"/>
+ <path style="fill: url(#radialGradient6352) rgb(0, 0, 0); fill-opacity: 1; stroke: rgb(136, 138, 133); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 4.9874617,9.5 L 43.039565,9.5 C 43.309619,9.5 43.527027,9.7276458 43.527027,10.010417 L 43.527027,33.989583 L 40.039565,37.5 L 4.9874617,37.5 C 4.7174079,37.5 4.5,37.272354 4.5,36.989583 L 4.5,10.010417 C 4.5,9.7276458 4.7174079,9.5 4.9874617,9.5 z " id="rect2063" sodipodi:nodetypes="ccccccccc"/>
+ <path style="opacity: 0.172414; fill: url(#linearGradient6372) rgb(0, 0, 0); fill-opacity: 1; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 14.78125,40 L 35.40625,40 C 35.41645,39.995518 35.423208,39.996022 35.46875,39.96875 C 35.559833,39.914206 35.707858,39.809986 35.875,39.6875 C 36.209283,39.442528 36.659837,39.093896 37.1875,38.65625 C 38.242827,37.780957 39.61066,36.608491 40.9375,35.40625 C 42.26434,34.204009 43.563777,32.96157 44.53125,32 C 45.014987,31.519215 45.417906,31.118778 45.6875,30.8125 C 45.822297,30.659361 45.910802,30.519277 45.96875,30.4375 C 45.983237,30.417056 45.991685,30.419536 46,30.40625 L 46,13.78125 L 14.78125,40 z " id="path6364" sodipodi:nodetypes="ccsssssssccc"/>
+ <path style="fill: none; fill-opacity: 1; stroke: rgb(255, 255, 255); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1;" d="M 2.78125,7.5 C 2.6253137,7.5 2.5,7.6253137 2.5,7.78125 L 2.5,39.21875 C 2.5,39.374686 2.6253136,39.5 2.78125,39.5 L 37.28125,39.5 C 40.921301,36.704635 42.365769,35.606734 45.5,32.25 L 45.5,7.78125 C 45.5,7.6253155 45.374683,7.5 45.21875,7.5 L 2.78125,7.5 z " id="path6351" sodipodi:nodetypes="ccccccccc"/>
+ <path style="fill: url(#linearGradient6333) rgb(0, 0, 0); fill-rule: evenodd; stroke: url(#radialGradient6382) rgb(0, 0, 0); stroke-width: 1px; stroke-linecap: butt; stroke-linejoin: round; stroke-opacity: 1; fill-opacity: 1;" d="M 46.5,30.5 C 46.5,35.5 40.5,40.5 35.5,40.5 C 35.5,40.5 39.932134,38.33738 39.5,33.5 C 43.879686,33.916135 46.5,30.5 46.5,30.5 z " id="path6322" sodipodi:nodetypes="cccc"/>
+ <path style="fill: url(#radialGradient6437) rgb(0, 0, 0); fill-opacity: 1; fill-rule: evenodd; stroke: none; stroke-width: 1px; stroke-linecap: butt; stroke-linejoin: round; stroke-opacity: 1; opacity: 0.732759;" d="M 45.71875 31.96875 C 44.577589 32.932531 42.679856 34.08934 40.03125 34.03125 C 40.059733 36.774444 38.699098 38.58751 37.46875 39.6875 C 38.953141 38.706251 40.825166 37.371805 41.03125 35.03125 C 43.192381 35.027997 44.619214 33.310655 45.6875 32.03125 C 45.693038 32.009581 45.713422 31.990426 45.71875 31.96875 z " id="path6339"/>
+ <path style="fill: url(#radialGradient6396) rgb(0, 0, 0); fill-opacity: 1; stroke: none; stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1; opacity: 0.344828;" d="M 2.78125,7 C 2.3536576,7 2,7.3536576 2,7.78125 L 2,31.09375 C 14.714701,22.184679 34.055102,15.625228 46,19.3125 L 46,7.78125 C 46,7.3536585 45.64634,7 45.21875,7 L 2.78125,7 z " id="path6384" sodipodi:nodetypes="ccccccc"/>
+ <path sodipodi:type="inkscape:offset" inkscape:radius="-1" inkscape:original="M 2.78125 6.5 C 2.0789071 6.5 1.5 7.0789071 1.5 7.78125 L 1.5 39.21875 C 1.5 39.921093 2.0789071 40.5 2.78125 40.5 L 35.5 40.5 C 40.5 40.5 46.5 35.5 46.5 30.5 L 46.5 7.78125 C 46.5 7.0789071 45.921091 6.5 45.21875 6.5 L 2.78125 6.5 z " style="fill: none; fill-opacity: 1; stroke: rgb(255, 255, 255); stroke-width: 1; stroke-linecap: round; stroke-linejoin: round; stroke-miterlimit: 4; stroke-dashoffset: 0pt; stroke-opacity: 1; opacity: 0.418103;" id="path6427" d="M 2.78125,7.5 C 2.628408,7.5 2.5,7.628408 2.5,7.78125 L 2.5,39.21875 C 2.5,39.371592 2.6284079,39.5 2.78125,39.5 L 35.5,39.5 C 37.666667,39.5 40.249358,38.362698 42.21875,36.625 C 44.188142,34.887302 45.5,32.6 45.5,30.5 L 45.5,7.78125 C 45.5,7.6284098 45.371589,7.5 45.21875,7.5 L 2.78125,7.5 z "/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/rapid/glade3/rapid-photo-downloader-about.png b/rapid/glade3/rapid-photo-downloader-about.png
new file mode 100644
index 0000000..0aefb1d
--- /dev/null
+++ b/rapid/glade3/rapid-photo-downloader-about.png
Binary files differ
diff --git a/rapid/glade3/rapid.glade b/rapid/glade3/rapid.glade
new file mode 100644
index 0000000..be01fa4
--- /dev/null
+++ b/rapid/glade3/rapid.glade
@@ -0,0 +1,2716 @@
+<?xml version="1.0"?>
+<glade-interface>
+ <!-- interface-requires gtk+ 2.16 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <widget class="GtkDialog" id="preferencesdialog">
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Preferences: Rapid Photo Downloader</property>
+ <property name="modal">True</property>
+ <property name="window_position">center-on-parent</property>
+ <property name="default_height">500</property>
+ <property name="icon">rapid-photo-downloader-about.png</property>
+ <property name="type_hint">dialog</property>
+ <property name="has_separator">False</property>
+ <signal name="destroy" handler="on_preferencesdialog_destroy"/>
+ <signal name="response" handler="on_response"/>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox2">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkHBox" id="hbox3">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolled_window">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="resize_mode">queue</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <widget class="GtkTreeView" id="treeview">
+ <property name="width_request">100</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="headers_visible">False</property>
+ <signal name="cursor_changed" handler="on_treeview_cursor_changed"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">5</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkNotebook" id="notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_border">False</property>
+ <child>
+ <widget class="GtkVBox" id="folder_tab">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-open</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Download Folder&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator1">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox9">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label16">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="download_folder_table">
+ <property name="visible">True</property>
+ <property name="n_rows">7</property>
+ <property name="n_columns">3</property>
+ <child>
+ <widget class="GtkVBox" id="subfolder_vbox">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="example_download_path_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;i&gt;Example: /home/user/photos&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;b&gt;Download Subfolders&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="lblPhotos1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Download folder:</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">Choose the download folder. Subfolders for the downloaded photos will be automatically created in this folder using the structure specified below.</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;b&gt;Download Folder&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="subfolder_warning_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="wrap">True</property>
+ <property name="wrap_mode">word-char</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label23">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="menu_label">Download Folders</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="download_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Download Folder</property>
+ </widget>
+ <packing>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="rename_tab">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox7">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox5">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-convert</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Image Rename&lt;/span&gt; </property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator2">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox12">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label24">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="rename_vbox">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label42">
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;b&gt;Image Rename&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkScrolledWindow" id="rename_scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <property name="window_placement_set">True</property>
+ <child>
+ <widget class="GtkViewport" id="viewport2">
+ <property name="visible">True</property>
+ <property name="resize_mode">queue</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <widget class="GtkVBox" id="rename_table_vbox">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="rename_example_table">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">3</property>
+ <child>
+ <widget class="GtkLabel" id="label17">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options"></property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="new_name_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">translators please ignore this</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="original_name_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">translators please ignore this</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label21">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="label" translatable="yes">&lt;i&gt;New:&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label20">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;i&gt;Original:&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;b&gt;Example&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="y_padding">12</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label25">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="menu_label">Rename</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="rename_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Image Rename</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="rename_options_tab">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox14">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox18">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image7">
+ <property name="visible">True</property>
+ <property name="icon_name">input-keyboard</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label10">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Rename Options&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator4">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox12">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkLabel" id="label29">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">&lt;b&gt;Sequence numbers&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox21">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label46">
+ <property name="visible">True</property>
+ <property name="xpad">12</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox13">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label47">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Specify the time in 24 hour format at which the &lt;i&gt;Downloads today&lt;/i&gt; sequence number should be reset.</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox23">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="label49">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Day start:</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label51">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Downloads today:</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label52">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Stored number:</property>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label54">
+ <property name="visible">True</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes"> </property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="sequence_vbox">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkHBox" id="hbox22">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkSpinButton" id="hour_spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">2</property>
+ <property name="xalign">1</property>
+ <property name="truncate_multiline">True</property>
+ <property name="adjustment">0 0 23 1 10 0</property>
+ <property name="numeric">True</property>
+ <signal name="value_changed" handler="on_hour_spinbutton_value_changed"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label50">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">:</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkSpinButton" id="minute_spinbutton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="width_chars">2</property>
+ <property name="xalign">1</property>
+ <property name="truncate_multiline">True</property>
+ <property name="adjustment">0 0 59 1 10 0</property>
+ <property name="numeric">True</property>
+ <signal name="value_changed" handler="on_minute_spinbutton_value_changed"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label53">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes"> hh:mm</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label48">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label44">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">&lt;b&gt;Compatibility with Other Operating Systems&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox16">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label32">
+ <property name="visible">True</property>
+ <property name="xpad">12</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="compatibility_table">
+ <property name="visible">True</property>
+ <property name="n_rows">9</property>
+ <property name="n_columns">2</property>
+ <child>
+ <widget class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Specify whether image and folder names should have any characters removed that are not allowed by other operating systems.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="strip_characters_checkbutton">
+ <property name="label" translatable="yes">Strip incompatible characters</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_strip_characters_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label33">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">12</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="rename_options_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Rename Options</property>
+ </widget>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="device_tab">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image6">
+ <property name="visible">True</property>
+ <property name="icon_name">media-flash</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label22">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Image Devices&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator5">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label41">
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">&lt;b&gt;Image Devices&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label18">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">Image devices are devices from which to download photos, such as cameras, memory cards or Portable Storage Devices.
+
+You can download photos from multiple image devices simultaneously.
+
+&lt;i&gt;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.&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox14">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkLabel" id="label26">
+ <property name="visible">True</property>
+ <property name="xpad">3</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="devices_table">
+ <property name="visible">True</property>
+ <property name="n_rows">3</property>
+ <property name="n_columns">2</property>
+ <property name="row_spacing">3</property>
+ <child>
+ <widget class="GtkCheckButton" id="autodetect_psd_checkbutton">
+ <property name="label" translatable="yes">Automatically detect Portable Storage Devices</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_autodetect_psd_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="autodetect_device_checkbutton">
+ <property name="label" translatable="yes">Automatically detect image devices</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_autodetect_device_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="autodetect_image_devices_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">6</property>
+ <property name="label" translatable="yes">If you enable automatic detection of Portable Storage Devices, the entire device will be scanned for images. On large devices, this could take some time.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label28">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox15">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkTable" id="devices2_table">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <child>
+ <widget class="GtkLabel" id="device_location_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">Image location:</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_SHRINK</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="device_location_explanation_label">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">If you disable automatic detection, choose the exact location of the images.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="device_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Image Devices</property>
+ </widget>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="backup_tab">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox7">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image8">
+ <property name="visible">True</property>
+ <property name="icon_name">drive-removable-media</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label27">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Backup&lt;/span&gt; </property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator6">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox9">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkLabel" id="label43">
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">&lt;b&gt;Backup&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox20">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label38">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="backup_table">
+ <property name="visible">True</property>
+ <property name="n_rows">8</property>
+ <property name="n_columns">4</property>
+ <child>
+ <widget class="GtkLabel" id="backup_location_explanation_label">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">If you disable automatic detection, choose the exact backup location.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="auto_detect_backup_checkbutton">
+ <property name="label" translatable="yes">Automatically detect backup devices</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_auto_detect_backup_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">You can have your photos backed up to multiple locations as they are downloaded, e.g. external hard drives.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">4</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="backup_checkbutton">
+ <property name="label" translatable="yes">Backup photos when downloading</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_backup_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">4</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="backup_identifier_explanation_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">6</property>
+ <property name="label" translatable="yes">Specify the folder in which backups are stored on the device.
+
+&lt;i&gt;Note: this will also be used to determine whether or not the device is used for backups. For each device you wish to use for backing up to, create a folder in it with this name.&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="backup_location_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Backup location:</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="backup_identifier_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">Backup folder name:</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">5</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="backup_example_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="ypad">6</property>
+ <property name="label" translatable="yes">&lt;i&gt;Example:&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="right_attach">3</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="example_backup_path_label">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ <property name="ypad">6</property>
+ <property name="label" translatable="yes">&lt;i&gt;/media/externaldrive/Photos&lt;/i&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEntry" id="backup_identifier_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <signal name="changed" handler="on_backup_identifier_entry_changed"/>
+ </widget>
+ <packing>
+ <property name="left_attach">3</property>
+ <property name="right_attach">4</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options"></property>
+ <property name="y_padding">12</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label39">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="backup_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Backup</property>
+ </widget>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="automation_tab">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkVBox" id="vbox4">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox10">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image4">
+ <property name="visible">True</property>
+ <property name="stock">gtk-execute</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label31">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Automation&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator7">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox11">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkLabel" id="label45">
+ <property name="xalign">0</property>
+ <property name="xpad">12</property>
+ <property name="label" translatable="yes">&lt;b&gt;Program Automation&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox17">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkLabel" id="label34"/>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="automation_table">
+ <property name="visible">True</property>
+ <property name="n_rows">7</property>
+ <property name="n_columns">3</property>
+ <child>
+ <widget class="GtkCheckButton" id="auto_unmount_checkbutton">
+ <property name="label" translatable="yes">Unmount ("eject") image device upon download completion</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_auto_unmount_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="auto_startup_checkbutton">
+ <property name="label" translatable="yes">Start downloading at program startup</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_auto_startup_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="auto_insertion_checkbutton">
+ <property name="label" translatable="yes">Start downloading upon image device insertion</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_auto_insertion_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="auto_exit_checkbutton">
+ <property name="label" translatable="yes">Exit program after completion of successful download</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_auto_exit_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="right_attach">3</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">24</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label35">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="automation_label">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Automation</property>
+ </widget>
+ <packing>
+ <property name="position">5</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="error_tab">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkVBox" id="vbox8">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="hbox13">
+ <property name="visible">True</property>
+ <property name="spacing">6</property>
+ <child>
+ <widget class="GtkImage" id="image9">
+ <property name="visible">True</property>
+ <property name="stock">gtk-dialog-error</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label40">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">&lt;span weight="bold" size="x-large"&gt;Error Handling&lt;/span&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator9">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox19">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkLabel" id="label36">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="error_table">
+ <property name="visible">True</property>
+ <property name="n_rows">14</property>
+ <property name="n_columns">2</property>
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes"> </property>
+ </widget>
+ <packing>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="label" translatable="yes">&lt;b&gt;Image Name Conflicts&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="backup_ignore_radiobutton">
+ <property name="label" translatable="yes">Ignore</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">backup_error_radiobutton</property>
+ <signal name="toggled" handler="on_backup_ignore_radiobutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">13</property>
+ <property name="bottom_attach">14</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="backup_warning_radiobutton">
+ <property name="label" translatable="yes">Report a warning</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">backup_error_radiobutton</property>
+ <signal name="toggled" handler="on_backup_warning_radiobutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">12</property>
+ <property name="bottom_attach">13</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="backup_error_radiobutton">
+ <property name="label" translatable="yes">Report an error</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_backup_error_radiobutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">11</property>
+ <property name="bottom_attach">12</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="missing_backup_label">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">&lt;b&gt;Missing Backup Devices&lt;/b&gt;</property>
+ <property name="use_markup">True</property>
+ </widget>
+ <packing>
+ <property name="right_attach">2</property>
+ <property name="top_attach">9</property>
+ <property name="bottom_attach">10</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="add_identifier_radiobutton">
+ <property name="label" translatable="yes">Add unique identifier</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">skip_download_radiobutton</property>
+ <signal name="toggled" handler="on_add_identifier_radiobutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">5</property>
+ <property name="bottom_attach">6</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="skip_download_radiobutton">
+ <property name="label" translatable="yes">Skip download</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">4</property>
+ <property name="bottom_attach">5</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">Choose whether to skip downloading the image, or to add a unique indentifier.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">3</property>
+ <property name="bottom_attach">4</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkCheckButton" id="indicate_download_error_checkbutton">
+ <property name="label" translatable="yes">Report an error</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_indicate_download_error_checkbutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">2</property>
+ <property name="bottom_attach">3</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label19">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">Specify what to do when an image of the same name has already been downloaded or backed up.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label3">
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">Specify what to do when there are no backup devices.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">10</property>
+ <property name="bottom_attach">11</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="ypad">12</property>
+ <property name="label" translatable="yes">When backing up, choose whether to overwrite an image on the backup device that has the same name, or skip backing it up.</property>
+ <property name="wrap">True</property>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">6</property>
+ <property name="bottom_attach">7</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="backup_duplicate_overwrite_radiobutton">
+ <property name="label" translatable="yes">Overwrite</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">backup_duplicate_skip_radiobutton</property>
+ <signal name="toggled" handler="on_backup_duplicate_overwrite_radiobutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">7</property>
+ <property name="bottom_attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="backup_duplicate_skip_radiobutton">
+ <property name="label" translatable="yes">Skip</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_backup_duplicate_skip_radiobutton_toggled"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">8</property>
+ <property name="bottom_attach">9</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label37">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="error_label">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Error Handling</property>
+ </widget>
+ <packing>
+ <property name="position">6</property>
+ <property name="tab_fill">False</property>
+ <property name="type">tab</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area2">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <widget class="GtkButton" id="help_button">
+ <property name="label">gtk-help</property>
+ <property name="response_id">-11</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="close_button">
+ <property name="label">gtk-close</property>
+ <property name="response_id">-7</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ <signal name="clicked" handler="on_close_button_clicked"/>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkAboutDialog" id="about">
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="icon">rapid-photo-downloader-about.png</property>
+ <property name="type_hint">normal</property>
+ <property name="program_name">Rapid Photo Downloader</property>
+ <property name="copyright" translatable="yes">Copyright Damon Lynch 2007-09</property>
+ <property name="comments" translatable="yes">Import your images efficiently and reliably</property>
+ <property name="website">http://www.damonlynch.net/rapid</property>
+ <property name="license" translatable="yes">Rapid Photo Downloader is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
+
+Rapid Photo Downloader is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with Rapid Photo Downloader; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.</property>
+ <property name="authors">Damon Lynch &lt;damonlynch@gmail.com&gt;</property>
+ <property name="translator_credits" comments="TRANSLATORS: Replace this string with your names, one name per line.">Martin Egger &lt;martin.egger@gmx.net&gt;
+Jose Luis Navarro &lt;jlnavarro111@gmail.com&gt;
+Abel O'Rian &lt;abel.orian@gmail.com&gt;
+Daniel Paessler &lt;daniel@paessler.org&gt;
+Michal Predotka &lt;mpredotka@googlemail.com&gt;
+Luca Reverberi &lt;thereve@gmail.com&gt;
+Mikko Ruohola &lt;polarfox@polarfox.net&gt;
+Sergei Sedov &lt;sedov@webmail.perm.ru&gt;
+Marco Solari &lt;marcosolari@gmail.com&gt;
+Julien Valroff &lt;julien@kirya.net&gt;</property>
+ <property name="logo">rapid-photo-downloader-about.png</property>
+ <property name="wrap_license">True</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkWindow" id="rapidapp">
+ <property name="width_request">600</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="title" translatable="yes">Rapid Photo Downloader</property>
+ <property name="icon">rapid-photo-downloader-about.png</property>
+ <signal name="destroy" handler="on_rapidapp_destroy"/>
+ <child>
+ <widget class="GtkVBox" id="vbox10">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkMenuBar" id="menubar3">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Photos</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menuitem7_menu">
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_download_pause">
+ <property name="label" translatable="yes">Download / Pause</property>
+ <property name="visible">True</property>
+ <property name="use_stock">False</property>
+ <signal name="activate" handler="on_download_button_clicked"/>
+ <accelerator key="Return" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <child internal-child="image">
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-convert</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_resequence">
+ <property name="label">Resequence</property>
+ <property name="use_stock">False</property>
+ <accelerator key="E" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <child internal-child="image">
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-sort-descending</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator2"/>
+ </child>
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_preferences">
+ <property name="label">gtk-preferences</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <signal name="activate" handler="on_menu_preferences_activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_quit">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <signal name="activate" handler="on_rapidapp_destroy"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menuitem10">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="menuitem10_menu">
+ <child>
+ <widget class="GtkCheckMenuItem" id="menu_display_thumbnails">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Thumbnails</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="on_menu_display_thumbnails_toggled"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkCheckMenuItem" id="menu_log_window">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Error Log</property>
+ <property name="use_underline">True</property>
+ <signal name="toggled" handler="on_menu_log_window_toggled"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator5">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menu_clear">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Clear Completed Downloads</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_menu_clear_activate"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="help_menuitem">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child>
+ <widget class="GtkMenu" id="help_menu">
+ <child>
+ <widget class="GtkMenuItem" id="menu_get_help_online">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Get Help Online...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_menu_get_help_online_activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menu_report_problem">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Report a Problem...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_menu_report_problem_activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menu_donate">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Make a Donation...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_menu_donate_activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="menu_translate">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">_Translate this Application...</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="on_menu_translate_activate"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="separator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkImageMenuItem" id="menu_about">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ <signal name="activate" handler="on_menu_about_activate"/>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="main_vbox">
+ <property name="visible">True</property>
+ <property name="spacing">12</property>
+ <child>
+ <widget class="GtkHBox" id="hbox6">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="media_collection_scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <widget class="GtkViewport" id="media_collection_viewport">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <child>
+ <widget class="GtkVBox" id="media_collection_vbox">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="hbox8">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="image_scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vscrollbar_policy">never</property>
+ <child>
+ <widget class="GtkViewport" id="image_viewport">
+ <property name="height_request">112</property>
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="buttons_hbox">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkHBox" id="statusbar_hbox">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHBox" id="download_progressbar_hbox">
+ <property name="visible">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkStatusbar" id="rapid_statusbar">
+ <property name="visible">True</property>
+ <property name="has_resize_grip">False</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVSeparator" id="vseparator1">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVBox" id="vbox15">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkHSeparator" id="hseparator3">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="speed_label">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"> </property>
+ <property name="width_chars">9</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkVSeparator" id="vseparator2">
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkEventBox" id="error_eventbox">
+ <property name="visible">True</property>
+ <signal name="button_press_event" handler="on_error_eventbox_button_press_event"/>
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkImage" id="warning_image">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="xpad">3</property>
+ <property name="stock">gtk-dialog-warning</property>
+ <property name="icon-size">1</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkImage" id="error_image">
+ <property name="visible">True</property>
+ <property name="xpad">3</property>
+ <property name="stock">gtk-dialog-error</property>
+ <property name="icon-size">1</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkStatusbar" id="statusbar1">
+ <property name="width_request">15</property>
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <widget class="GtkDialog" id="logdialog">
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="border_width">5</property>
+ <property name="title" translatable="yes">Error Log</property>
+ <property name="default_width">600</property>
+ <property name="default_height">400</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="icon">rapid-photo-downloader-about.png</property>
+ <property name="type_hint">dialog</property>
+ <property name="has_separator">False</property>
+ <signal name="close" handler="on_logdialog_close"/>
+ <signal name="response" handler="on_logdialog_response"/>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox4">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkScrolledWindow" id="log_scrolledwindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <widget class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <child>
+ <widget class="GtkTextView" id="log_textview">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="editable">False</property>
+ <property name="cursor_visible">False</property>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area4">
+ <property name="visible">True</property>
+ <property name="layout_style">end</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <widget class="GtkButton" id="button3">
+ <property name="label">gtk-close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_stock">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+</glade-interface>
diff --git a/rapid/gnomeglade.py b/rapid/gnomeglade.py
new file mode 100644
index 0000000..c0b0860
--- /dev/null
+++ b/rapid/gnomeglade.py
@@ -0,0 +1,166 @@
+### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Utility classes for working with glade files.
+
+"""
+# modified by Damon Lynch May 2009 to update i18n
+
+import gtk
+import gtk.glade
+import gnome
+import gnome.ui
+#import gettext
+import config
+from common import Configi18n
+
+class Base(object):
+ """Base class for all glade objects.
+
+ This class handles loading the xml glade file and connects
+ all methods name 'on_*' to the signals in the glade file.
+
+ The handle to the xml file is stored in 'self.xml'. The
+ toplevel widget is stored in 'self.widget'.
+
+ In addition it calls widget.set_data("pyobject", self) - this
+ allows us to get the python object given only the 'raw' gtk+
+ object, which is sadly sometimes necessary.
+ """
+
+ def __init__(self, file, root, override={}):
+ """Load the widgets from the node 'root' in file 'file'.
+
+ Automatically connects signal handlers named 'on_*'.
+ """
+ global _
+ _ = Configi18n._
+ if Configi18n.locale_path:
+ gtk.glade.bindtextdomain(config.APP_NAME, Configi18n.locale_path)
+ gtk.glade.textdomain(config.APP_NAME)
+ self.xml = gtk.glade.XML(file, root, typedict=override )
+ handlers = {}
+ for h in filter(lambda x:x.startswith("on_"), dir(self.__class__)):
+ handlers[h] = getattr(self, h)
+ self.xml.signal_autoconnect( handlers )
+ self.widget = getattr(self, root)
+ self.widget.set_data("pyobject", self)
+
+ def __getattr__(self, key):
+ """Allow glade widgets to be accessed as self.widgetname.
+ """
+ widget = self.xml.get_widget(key)
+ if widget: # cache lookups
+ setattr(self, key, widget)
+ return widget
+ raise AttributeError(key)
+
+ def flushevents(self):
+ """Handle all the events currently in the main queue and return.
+ """
+ while gtk.events_pending():
+ gtk.main_iteration();
+
+ def _map_widgets_into_lists(self, widgetnames):
+ """Put sequentially numbered widgets into lists.
+
+ e.g. If an object had widgets self.button0, self.button1, ...,
+ then after a call to object._map_widgets_into_lists(["button"])
+ object has an attribute self.button == [self.button0, self.button1, ...]."
+ """
+ for item in widgetnames:
+ setattr(self,item, [])
+ lst = getattr(self,item)
+ i = 0
+ while 1:
+ key = "%s%i"%(item,i)
+ try:
+ val = getattr(self, key)
+ except AttributeError:
+ break
+ lst.append(val)
+ i += 1
+
+
+class Component(Base):
+ """A convenience base class for widgets which use glade.
+ """
+
+ def __init__(self, file, root, override={}):
+ Base.__init__(self, file, root, override)
+
+
+class GtkApp(Base):
+ """A convenience base class for gtk+ apps created in glade.
+ """
+
+ def __init__(self, file, root=None):
+ Base.__init__(self, file, root)
+
+ def main(self):
+ """Enter the gtk main loop.
+ """
+ gtk.main()
+
+ def quit(self, *args):
+ """Signal the gtk main loop to quit.
+ """
+ gtk.main_quit()
+
+
+class GnomeApp(GtkApp):
+ """A convenience base class for apps created in glade.
+ """
+
+ def __init__(self, name, version, file, root):
+ """Initialise program 'name' and version from 'file' containing root node 'root'.
+ """
+ self.program = gnome.program_init(name, version)
+ GtkApp.__init__(self,file,root)
+ if 0:
+ self.client = gnome.ui.Client()
+ self.client.disconnect()
+ def connected(*args):
+ print "CONNECTED", args
+ def cb(name):
+ def cb2(*args):
+ print name, args, "\n"
+ return cb2
+ self.client.connect("connect", cb("CON"))
+ self.client.connect("die", cb("DIE"))
+ self.client.connect("disconnect", cb("DIS"))
+ self.client.connect("save-yourself", cb("SAVE"))
+ self.client.connect("shutdown-cancelled", cb("CAN"))
+ self.client.connect_to_session_manager()
+
+
+def load_pixbuf(fname, size=0):
+ """Load an image from a file as a pixbuf, with optional resizing.
+ """
+ image = gtk.Image()
+ image.set_from_file(fname)
+ image = image.get_pixbuf()
+ if size:
+ aspect = float(image.get_height()) / image.get_width()
+ image = image.scale_simple(size, int(aspect*size), 2)
+ return image
+
+def url_show(url):
+ return gnome.url_show(url)
+
+def FileEntry(*args):
+ return gnome.ui.FileEntry(*args)
+
diff --git a/rapid/higdefaults.py b/rapid/higdefaults.py
new file mode 100644
index 0000000..9dfd7e5
--- /dev/null
+++ b/rapid/higdefaults.py
@@ -0,0 +1,8 @@
+# -*- coding: latin1 -*-
+VERTICAL_CONTROL_LABEL_SPACE = CONTROL_LABEL_SPACE = 12
+CONTROL_IN_TABLE_SPACE = 6
+WINDOW_BORDER_SPACE = 12
+NESTED_CONTROLS_SPACE = 24
+VERTICAL_CONTROL_SPACE = 18
+VERTICAL_GROUP_SPACE = 24
+HORIZONTAL_GROUP_SPACE = 24
diff --git a/rapid/idletube.py b/rapid/idletube.py
new file mode 100644
index 0000000..86ff1a4
--- /dev/null
+++ b/rapid/idletube.py
@@ -0,0 +1,205 @@
+
+# Copyright (c) 2005 Antoon Pardon
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+from threading import Lock
+from thread import get_ident
+
+from types import BooleanType as UnConnected
+
+UnRegistered, Registered = False, True
+
+class EOInformation(Exception):
+ pass
+
+class TubeAccess(Exception):
+ pass
+
+class Fifo:
+
+ def __init__(self):
+ self.fifo = []
+
+ def put(self, item):
+ self.fifo.append(item)
+
+ def get(self):
+ return self.fifo.pop(0)
+
+ def size(self):
+ return len(self.fifo)
+
+class Tube:
+
+ def __init__(self, maxsize, lck = Lock, container = None):
+ if container is None:
+ container = Fifo()
+ self.readers = set()
+ self.writers = set()
+ self.container = container
+ self.maxsize = maxsize
+ self.cb_arglst = []
+ self.cb_src = UnRegistered
+ self.in_use = Lock()
+ self.nowriter = lck()
+ self.full = lck()
+ self.empty = lck()
+ self.empty.acquire()
+ self.nowriter.acquire()
+
+ def open(self, access = 'r', *to):
+ thrd = get_ident()
+ access = access.lower()
+ self.in_use.acquire()
+ if 'w' in access:
+ if len(self.writers) == 0:
+ for _ in self.readers:
+ self.nowriter.release()
+ self.writers.add(thrd)
+ if 'r' in access:
+ self.readers.add(thrd)
+ if len(self.writers) == 0:
+ self.in_use.release()
+ self.nowriter.acquire(*to)
+ else:
+ self.in_use.release()
+ else:
+ self.in_use.release()
+
+ def close(self, access = 'rw'):
+ thrd = get_ident()
+ access = access.lower()
+ self.in_use.acquire()
+ if 'r' in access:
+ self.readers.discard(thrd)
+ if 'w' in access:
+ self.writers.discard(thrd)
+## print "have", self.writers, "writers"
+ if len(self.writers) == 0:
+ if self.container.size() == 0:
+## print "emptying container, as size is", self.container.size()
+ self.empty.release()
+ if self.cb_src is Registered and len(self.readers) > 0:
+## print "adding callback"
+ self.cb_src = gob.idle_add(self._idle_callback)
+## else:
+## print "container size not empty, is", self.container.size()
+ for _ in self.readers:
+## print "putting EOInformation"
+ self.container.put(EOInformation)
+ self.in_use.release()
+
+ def size(self):
+ self.in_use.acquire()
+ size = self.container.size()
+ self.in_use.release()
+ return size
+
+ def get(self, *to):
+ thrd = get_ident()
+ if thrd not in self.readers:
+ raise TubeAccess, "Thread has no read access for tube"
+ self.empty.acquire(*to)
+ self.in_use.acquire()
+ size = self.container.size()
+ if size == self.maxsize:
+ self.full.release()
+ item = self.container.get()
+ if size != 1:
+ self.empty.release()
+ elif type(self.cb_src) is not UnConnected:
+ gob.source_remove(self.cb_src)
+ self.cb_src = Registered
+ self.in_use.release()
+ if item is EOInformation:
+ raise EOInformation
+ else:
+ return item
+
+ def put(self, item, *to):
+ thrd = get_ident()
+ if thrd not in self.writers:
+ raise TubeAccess, "Thread has no write access for tube"
+ if thrd in self.readers:
+ self._put_rw(item)
+ else:
+ self._put_wo(item, *to)
+
+ def _put_wo(self, item, *to):
+ self.full.acquire(*to)
+ self.in_use.acquire()
+ size = self.container.size()
+ if size == 0:
+ self.empty.release()
+ if self.cb_src is Registered:
+ #gdk.threads_enter()
+ self.cb_src = gob.idle_add(self._idle_callback)
+ #gdk.threads_leave()
+ self.container.put(item)
+ if size + 1 < self.maxsize:
+ self.full.release()
+ self.in_use.release()
+
+ def _put_rw(self, item):
+ self.in_use.acquire()
+ size = self.container.size()
+ if size == 0:
+ self.empty.release()
+ if self.cb_src is Registered:
+ self.cb_src = gob.idle_add(self._idle_callback)
+ self.container.put(item)
+ self.in_use.release()
+
+ def _idle_callback(self):
+ self.in_use.acquire()
+ lst = self.cb_arglst.pop(0)
+ self.in_use.release()
+ func = lst[0]
+ lst[0] = self
+ ret_val = func(*lst)
+ self.in_use.acquire()
+ if ret_val:
+ lst[0] = func
+ self.cb_arglst.append(lst)
+ elif self.cb_arglst == []:
+ self.cb_src = UnRegistered
+ self.in_use.release()
+ return self.cb_src is not UnRegistered
+
+
+def tube_add_watch(tube, callback, *args):
+
+ global gob #, gdk
+ import gobject as gob
+ #import gtk.gdk as gdk
+
+ tube.in_use.acquire()
+ tube.cb_arglst.append([callback] + list(args))
+ if tube.cb_src is UnRegistered:
+ if tube.container.size() == 0:
+ tube.cb_src = Registered
+ else:
+ tube.cb_src = gob.idle_add(tube._idle_callback)
+ tube.in_use.release()
+
+def tube_remove_watch(tube):
+## tube.in_use.acquire()
+## gob.source_remove(tube.cb_src)
+## tube._idle_callback.handler_block(tube.cb_src)
+ pass
diff --git a/rapid/media.py b/rapid/media.py
new file mode 100755
index 0000000..f4342c6
--- /dev/null
+++ b/rapid/media.py
@@ -0,0 +1,180 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+
+import config
+import common
+
+import operator
+
+def getDefaultPhotoLocation():
+ for default in config.DEFAULT_PHOTO_LOCATIONS:
+ path = common.getFullPath(default)
+ if os.path.isdir(path):
+ return path
+ return common.getFullPath('')
+
+def isImageMedia(path):
+ """ Returns true if directory specifies some media with photos on it """
+
+ if os.path.isdir(os.path.join(path, "DCIM")):
+ # is very likely a memory card, or something like that!
+ return True
+ else:
+ return False
+
+
+def isBackupMedia(path, identifier, writeable=True):
+ """ Test to see if path is used as a backup medium for storing images
+
+ If writeable is True, the directory must be writeable by the user """
+ suitable = False
+ if os.path.isdir(os.path.join(path, identifier)):
+ if writeable:
+ suitable = os.access(os.path.join(path, identifier), os.W_OK)
+ else:
+ suitable = True
+ return suitable
+
+def isImage(fileName):
+ ext = os.path.splitext(fileName)[1].lower()[1:]
+ return (ext in config.RAW_FILE_EXTENSIONS) or (ext in config.NON_RAW_IMAGE_FILE_EXTENSIONS)
+
+class Media:
+ """ Generic class for media holding images """
+ def __init__(self, path, volume = None):
+ """
+ volume is a gnomevfs volume
+ """
+
+ self.path = path
+ self.volume = volume
+
+
+ def prettyName(self, limit=config.MAX_LENGTH_DEVICE_NAME):
+ """
+ Returns a name for the media, useful for display.
+
+ If the media is from a gnomevfs volume, returns the gnome name.
+
+ Else. returns the last part of the mount point after stripping out
+ underscores.
+ """
+
+ if self.volume:
+ return self.volume.get_name(limit)
+ else:
+ name = os.path.split(self.path)[1]
+ name = name.replace('_', ' ')
+ v = name
+ if limit:
+ if len(v) > limit:
+ v = v[:limit] + '...'
+ return v
+
+ def getPath(self):
+ return self.path
+
+
+class CardMedia(Media):
+ """Compact Flash cards, etc."""
+ def __init__(self, path, volume = None, doNotScan=True):
+ """
+ volume is a gnomevfs volume
+ """
+ Media.__init__(self, path, volume)
+ if not doNotScan:
+ self.scanMedia()
+
+ def scanMedia(self):
+ """ creates a list of images on a path, recursively scanning
+
+ images are sorted by modification time"""
+
+ self.images = []
+ self.imageSizeSum = 0
+ for root, dirs, files in os.walk(self.path):
+ for name in files:
+ if isImage(name):
+ image = os.path.join(root, name)
+ size = os.path.getsize(image)
+ modificationTime = os.path.getmtime(image)
+ self.images.append((name, root, size, modificationTime),)
+ self.imageSizeSum += size
+ self.images.sort(key=operator.itemgetter(3))
+ self.noImages = len(self.images)
+
+ def setMedia(self, images, imageSizeSum, noImages):
+ self.images = images
+ self.imageSizeSum = imageSizeSum
+ self.noImages = noImages
+
+ def numberOfImages(self):
+ return self.noImages
+
+ def sizeOfImages(self, humanReadable = True):
+ if humanReadable:
+ return common.formatSizeForUser(self.imageSizeSum)
+ else:
+ return self.imageSizeSum
+
+ def firstImage(self):
+ if self.images:
+ return self.images[0]
+ else:
+ return None
+
+
+def scanForImageMedia(path):
+ """ returns a list of paths that contain images on media produced by a digital camera """
+
+ media = []
+ for i in os.listdir(path):
+ p = os.path.join(path, i)
+ if os.path.isdir(p):
+ if isImageMedia(p):
+ media.append(p)
+ return media
+
+def scanForBackupMedia(path, identifier):
+ """ returns a list of paths that contains backed up images """
+
+ media = []
+ for i in os.listdir(path):
+ p = os.path.join(path, i)
+ if os.path.isdir(p):
+ if isBackupMedia(p, identifier):
+ media.append(os.path.join(p, identifier))
+ return media
+
+
+if __name__ == '__main__':
+ print "Card media:"
+ for m in scanForImageMedia('/media'):
+ media = CardMedia(m)
+ print media.prettyName()
+ print media.numberOfImages()
+ print media.sizeOfImages()
+
+ print "\nBackup media:"
+ for m in scanForBackupMedia('/media', 'photos'):
+ print m
+
+ print "\nDefault download folder: ", getDefaultPhotoLocation()
diff --git a/rapid/metadata.py b/rapid/metadata.py
new file mode 100755
index 0000000..8fc6820
--- /dev/null
+++ b/rapid/metadata.py
@@ -0,0 +1,387 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import re
+import datetime
+import sys
+import config
+
+try:
+ import pyexiv2
+except ImportError:
+ sys.stderr.write("You need to install pyexiv2, the python binding for exiv2, to run this program.\n" )
+ sys.exit(1)
+
+#only pyexiv2 0.1.2 and 0.1.3 use the "Rational" class
+#is there a superior way to find which version of pyexiv2 is being used?
+if 'Rational' in dir(pyexiv2):
+ usesRational = True
+else:
+ usesRational = False
+
+
+class MetaData(pyexiv2.Image):
+ """
+ Class providing human readable access to image metadata
+ """
+
+ def aperture(self, missing=''):
+ """
+ Returns in string format the floating point value of the image's aperture.
+
+ Returns missing if the metadata value is not present.
+ """
+
+ try:
+ if usesRational:
+ a = self["Exif.Photo.FNumber"]
+ a0, a1 = str(a).split('/')
+ else:
+ a0, a1 = self["Exif.Photo.FNumber"]
+ a = float(a0) / float(a1)
+ return "%.1f" % a
+ except:
+ return missing
+
+ def iso(self, missing=''):
+ """
+ Returns in string format the integer value of the image's ISO.
+
+ Returns missing if the metadata value is not present.
+ """
+ try:
+ return "%s" % (self["Exif.Photo.ISOSpeedRatings"])
+ except:
+ return missing
+
+ def exposureTime(self, alternativeFormat=False, missing=''):
+ """
+ Returns in string format the exposure time of the image.
+
+ Returns missing if the metadata value is not present.
+
+ alternativeFormat is useful if the value is going to be used in a
+ purpose where / is an invalid character, e.g. file system names.
+
+ alternativeFormat is False:
+ For exposures less than one second, the result is formatted as a
+ fraction e.g. 1/125
+ For exposures greater than or equal to one second, the value is
+ formatted as an integer e.g. 30
+
+ alternativeFormat is True:
+ For exposures less than one second, the result is formatted as an
+ integer e.g. 125
+ For exposures less than one second but more than or equal to
+ one tenth of a second, the result is formatted as an integer
+ e.g. 3 representing 3/10 of a second
+ For exposures greater than or equal to one second, the value is
+ formatted as an integer with a trailing s e.g. 30s
+ """
+
+ try:
+ if usesRational:
+ e = str(self["Exif.Photo.ExposureTime"])
+ e0, e1 = e.split('/')
+ e0 = int(e0)
+ e1 = int(e1)
+ else:
+ e0, e1 = self["Exif.Photo.ExposureTime"]
+
+ if e1 > e0:
+ if alternativeFormat:
+ if e0 == 1:
+ return str(e1)
+ else:
+ return str(e0)
+ else:
+ return e
+ elif e0 > e1:
+ e = float(e0) / e1
+ if alternativeFormat:
+ return "%.0fs" % e
+ else:
+ return "%.0f" % e
+ else:
+ return "1s"
+ except:
+ return missing
+
+ def focalLength(self, missing=''):
+ """
+ Returns in string format the focal length of the lens used to record the image.
+
+ Returns missing if the metadata value is not present.
+ """
+ try:
+ if usesRational:
+ f = str(self["Exif.Photo.FocalLength"])
+ f0, f1 = f.split('/')
+ else:
+ f0, f1 = self["Exif.Photo.FocalLength"]
+
+ f0 = float(f0)
+ if not f1:
+ f1 = 1.0
+ else:
+ f1 = float(f1)
+
+ return "%.0f" % (f0 / f1)
+ except:
+ return missing
+
+
+ def cameraMake(self, missing=''):
+ """
+ Returns in string format the camera make (manufacturer) used to record the image.
+
+ Returns missing if the metadata value is not present.
+ """
+ try:
+ return self["Exif.Image.Make"].strip()
+ except:
+ return missing
+
+ def cameraModel(self, missing=''):
+ """
+ Returns in string format the camera model used to record the image.
+
+ Returns missing if the metadata value is not present.
+ """
+ try:
+ return self["Exif.Image.Model"].strip()
+ except:
+ return missing
+
+ def cameraSerial(self, missing=''):
+ try:
+ keys = self.exifKeys()
+ if 'Exif.Canon.SerialNumber' in keys:
+ v = self['Exif.Canon.SerialNumber']
+ elif 'Exif.Nikon3.SerialNumber' in keys:
+ v = self['Exif.Nikon3.SerialNumber']
+ elif 'Exif.OlympusEq.SerialNumber' in keys:
+ v = self['Exif.OlympusEq.SerialNumber']
+ elif 'Exif.Olympus.SerialNumber' in keys:
+ v = self['Exif.Olympus.SerialNumber']
+ elif 'Exif.Olympus.SerialNumber2' in keys:
+ v = self['Exif.Olympus.SerialNumber2']
+ elif 'Exif.Panasonic.SerialNumber' in keys:
+ v = self['Exif.Panasonic.SerialNumber']
+ elif 'Exif.Fujifilm.SerialNumber' in keys:
+ v = self['Exif.Fujifilm.SerialNumber']
+ elif 'Exif.Image.CameraSerialNumber' in keys:
+ v = self['Exif.Image.CameraSerialNumber']
+ else:
+ return missing
+ return str(v)
+ except:
+ return missing
+
+ def shutterCount(self, missing=''):
+ try:
+ keys = self.exifKeys()
+ if 'Exif.Nikon3.ShutterCount' in keys:
+ v = self['Exif.Nikon3.ShutterCount']
+ elif 'Exif.Canon.ImageNumber' in keys:
+ v = self['Exif.Canon.ImageNumber']
+ else:
+ return missing
+ return str(v)
+ except:
+ return missing
+
+ def ownerName(self, missing=''):
+ """ returns camera name recorded by select Canon cameras"""
+ try:
+ return self['Exif.Canon.OwnerName'].strip()
+ except:
+ return missing
+
+ def shortCameraModel(self, includeCharacters = '', missing=''):
+ """
+ Returns in shorterned string format the camera model used to record the image.
+
+ Returns missing if the metadata value is not present.
+
+ The short format is determined by the first occurence of a digit in the
+ camera model, including all alphaNumeric characters before and after
+ that digit up till a non-alphanumeric character.
+
+ Canon "Mark" designations are shortened prior to conversion.
+
+ Examples:
+ Canon EOS 300D DIGITAL -> 300D
+ Canon EOS 5D -> 5D
+ Canon EOS 5D Mark II -> 5DMkII
+ NIKON D2X -> D2X
+ NIKON D70 -> D70
+ X100,D540Z,C310Z -> X100
+
+ The optional includeCharacters allows additional characters to appear
+ before and after the digits.
+ Note: special includeCharacters MUST be escaped as per syntax of a
+ regular expressions (see documentation for module re)
+
+ Examples:
+
+ includeCharacters = '':
+ DSC-P92 -> P92
+ includeCharacters = '\-':
+ DSC-P92 -> DSC-P92
+
+ If a digit is not found in the camera model, the full length camera
+ model is returned.
+
+ Note: assume exif values are in ENGLISH, regardless of current platform
+ """
+ m = self.cameraModel()
+ m = m.replace(' Mark ', 'Mk')
+ if m:
+ s = r"(?:[^a-zA-Z0-9%s]?)(?P<model>[a-zA-Z0-9%s]*\d+[a-zA-Z0-9%s]*)"\
+ % (includeCharacters, includeCharacters, includeCharacters)
+ r = re.search(s, m)
+ if r:
+ return r.group("model")
+ else:
+ return m.strip()
+ else:
+ return missing
+
+ def dateTime(self, missing=''):
+ """
+ Returns in python datetime format the date and time the image was
+ recorded.
+
+ Trys to get value from exif key "Exif.Photo.DateTimeOriginal".
+ If that does not exist, trys key "Exif.Image.DateTime"
+
+ Returns missing either metadata value is not present.
+ """
+ keys = self.exifKeys()
+ try:
+ if "Exif.Photo.DateTimeOriginal" in keys:
+ return self["Exif.Photo.DateTimeOriginal"]
+ else:
+ return self["Exif.Image.DateTime"]
+ except:
+ return missing
+
+ def subSeconds(self, missing='00'):
+ """ returns the subsecond the image was taken, as recorded by the camera"""
+ try:
+ return str(self["Exif.Photo.SubSecTimeOriginal"])
+ except:
+ return missing
+
+ def orientation(self, missing=''):
+ """
+ Returns the orientation of the image, as recorded by the camera
+ """
+ try:
+ return self['Exif.Image.Orientation']
+ except:
+ return missing
+
+class DummyMetaData(MetaData):
+ """
+ Class which gives metadata values for an imaginary image.
+
+ Useful for displaying in preference examples etc. when no image is ready to
+ be downloaded.
+
+ See MetaData class for documentation of class methods.
+ """
+
+ def __init__(self):
+ pass
+
+ def readMetadata(self):
+ pass
+
+ def aperture(self, missing=''):
+ return "2.0"
+
+ def iso(self, missing=''):
+ return "100"
+
+ def exposureTime(self, alternativeFormat=False, missing=''):
+ if alternativeFormat:
+ return "4000"
+ else:
+ return "1/4000"
+
+ def focalLength(self, missing=''):
+ return "135"
+
+ def cameraMake(self, missing=''):
+ return "Canon"
+
+ def cameraModel(self, missing=''):
+ return "Canon EOS 5D"
+
+ def shortCameraModel(self, includeCharacters = '', missing=''):
+ return "5D"
+
+ def cameraSerial(self, missing=''):
+ return '730402168'
+
+ def shutterCount(self, missing=''):
+ return '387'
+
+ def ownerName(self, missing=''):
+ return 'Photographer Name'
+
+ def dateTime(self, missing=''):
+ return datetime.datetime.now()
+
+ def subSeconds(self, missing='00'):
+ return '57'
+
+ def orientation(self, missing=''):
+ return 1
+
+if __name__ == '__main__':
+ import sys
+
+ if (len(sys.argv) != 2):
+ print 'Usage: ' + sys.argv[0] + ' path/to/photo/containing/metadata'
+ m = DummyMetaData()
+
+ else:
+ m = MetaData(sys.argv[1])
+ m.readMetadata()
+
+# for i in m.exifKeys():
+# print i
+ print "f"+ m.aperture('missing ')
+ print "ISO " + m.iso('missing ')
+ print m.exposureTime(missing='missing ') + " sec"
+ print m.exposureTime(alternativeFormat=True, missing='missing ')
+ print m.focalLength('missing ') + "mm"
+ print m.cameraMake()
+ print m.cameraModel()
+ print m.shortCameraModel()
+ print m.shortCameraModel(includeCharacters = "\-")
+ print m.dateTime()
+ print m.orientation()
+ print 'Serial number:', m.cameraSerial()
+ print 'Shutter count:', m.shutterCount()
+ print 'Subseconds:', m.subSeconds()
+
diff --git a/rapid/misc.py b/rapid/misc.py
new file mode 100644
index 0000000..1e023ad
--- /dev/null
+++ b/rapid/misc.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# modified by Damon Lynch 2009 to remove default bold formatting and alignment
+"""Module of commonly used helper classes and functions
+
+"""
+
+import gtk
+
+def run_dialog( text, secondarytext=None, parent=None, messagetype=gtk.MESSAGE_WARNING, buttonstype=gtk.BUTTONS_OK, extrabuttons=[]):
+ """Run a dialog with text 'text'.
+ Extra buttons are passed as tuples of (button label, response id).
+ """
+ d = gtk.MessageDialog(None,
+ gtk.DIALOG_DESTROY_WITH_PARENT,
+ messagetype,
+ buttonstype,
+ text
+ )
+ if parent:
+ d.set_transient_for(parent.widget.get_toplevel())
+ for b,rid in extrabuttons:
+ d.add_button(b,rid)
+ d.vbox.set_spacing(12)
+ d.format_secondary_text(secondarytext)
+ ret = d.run()
+ d.destroy()
+ return ret
diff --git a/rapid/paths.py b/rapid/paths.py
new file mode 100644
index 0000000..0653324
--- /dev/null
+++ b/rapid/paths.py
@@ -0,0 +1,40 @@
+### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import os
+
+_locale_dir = ( #LOCALEDIR#
+)
+_help_dir = ( #HELPDIR#
+)
+_share_dir = ( #SHAREDIR#
+)
+
+appdir = os.path.dirname(__file__)
+
+if not _locale_dir: _locale_dir = os.path.join(appdir,"po")
+if not _help_dir: _help_dir = os.path.join(appdir,"help")
+if not _share_dir: _share_dir = appdir
+
+def locale_dir(*args): # i18n files
+ return os.path.join(_locale_dir, *args)
+
+def help_dir(*args): # help
+ return os.path.join(_help_dir, *args)
+
+def share_dir(*args): # glade + pixmaps
+ return os.path.join(_share_dir, *args)
+
diff --git a/rapid/prefs.py b/rapid/prefs.py
new file mode 100644
index 0000000..6912138
--- /dev/null
+++ b/rapid/prefs.py
@@ -0,0 +1,182 @@
+### Copyright (C) 2002-2006 Stephen Kennedy <stevek@gnome.org>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+### Modified August 2007 by Damon Lynch to allow use of list value preferences
+
+"""Module to help implement 'instant-apply' preferences.
+
+Usage:
+
+import prefs
+defaults = {
+ "colour" : prefs.Value(prefs.STRING, "red")
+ "size" : prefs.Value(prefs.INT, 10)
+}
+
+p = prefs.Preferences("/apps/myapp", defaults)
+# use variables as if they were normal attributes.
+draw(p.colour, p.size)
+# settings are persistent. (saved in gconf)
+p.color = "blue"
+
+"""
+
+class Value(object):
+ """Represents a settable preference.
+ """
+
+ __slots__ = ["type", "default", "current"]
+
+ def __init__(self, t, d):
+ """Create a value.
+
+ t : a string : one of ("bool", "int", "string", "list")
+ d : the default value, also the initial value
+ """
+ self.type = t
+ self.default = d
+ self.current = d
+
+ def setfunc(self, gconf, rootkey, attr):
+ setfunc = getattr(gconf, "set_%s" % self.type)
+ setfunc("%s/%s" % (rootkey, attr), self.current)
+
+ def getfunc(self, gconf, rootkey, attr):
+ getfunc = getattr(gconf, "get_%s" % self.type)
+ return getfunc("%s/%s" % (rootkey, attr))
+
+
+class ListValue(Value):
+ """
+ Represents a list type settable preference.
+ """
+
+ __slots__ = Value.__slots__ + ["list_type"]
+ def __init__(self, list_type, d):
+ """
+ Create a list value.
+
+ d : the default value, also the initial value
+ list_type: the type of elements the list contains
+ """
+ Value.__init__(self, LIST, d)
+ self.list_type = list_type
+
+ def setfunc(self, gconf, rootkey, attr):
+ setfunc = getattr(gconf, "set_list")
+ setfunc("%s/%s" % (rootkey, attr), self.list_type, self.current)
+
+ def getfunc(self, gconf, rootkey, attr):
+ getfunc = getattr(gconf, "get_list")
+ return getfunc("%s/%s" % (rootkey, attr), self.list_type)
+
+
+# maybe fall back to ConfigParser if gconf is unavailable.
+import gconf
+
+# types of values allowed
+BOOL = "bool"
+INT = "int"
+STRING = "string"
+FLOAT = "float"
+LIST = "list"
+# PAIR = "pair"
+STRING_LIST = gconf.VALUE_STRING
+INT_LIST = gconf.VALUE_INT
+BOOL_LIST = gconf.VALUE_BOOL
+FLOAT_LIST = gconf.VALUE_FLOAT
+##
+
+class Preferences(object):
+ """Persistent preferences object.
+
+ Example:
+ import prefs
+ defaults = {"spacing": prefs.Value(prefs.INT, 4),
+ "font": prefs.Value(prefs.STRING, "monospace") }
+ p = prefs.Prefs("myapp", defaults)
+ print p.font
+ p.font = "sans" # written to gconf too
+ p2 = prefs.Prefs("myapp", defaults)
+ print p.font # prints "sans"
+ """
+
+ def __init__(self, rootkey, initial):
+ """Create a preferences object.
+
+ Settings are initialised with 'initial' and then overriden
+ from values in the gconf database if available.
+
+ rootkey : the root gconf key where the values will be stored
+ initial : a dictionary of string to Value objects.
+ """
+ self.__dict__["_gconf"] = gconf.client_get_default()
+ self.__dict__["_listeners"] = []
+ self.__dict__["_rootkey"] = rootkey
+ self.__dict__["_prefs"] = initial
+ self._gconf.add_dir(rootkey, gconf.CLIENT_PRELOAD_NONE)
+ self._gconf.notify_add(rootkey, self._on_preference_changed)
+ for key, value in self._prefs.items():
+ gval = self._gconf.get_without_default("%s/%s" % (rootkey, key) )
+ if gval != None:
+ value.current = value.getfunc(self._gconf, rootkey, key)
+
+ def __getattr__(self, attr):
+ return self._prefs[attr].current
+
+ def get_default(self, attr):
+ return self._prefs[attr].default
+
+ def __setattr__(self, attr, val):
+ value = self._prefs[attr]
+
+ if value.current != val:
+ value.current = val
+ value.setfunc(self._gconf, self._rootkey, attr)
+
+ try:
+ for l in self._listeners:
+ l(attr,val)
+ except StopIteration:
+ pass
+
+ def _on_preference_changed(self, client, timestamp, entry, extra):
+ attr = entry.key[ entry.key.rindex("/")+1 : ]
+ try:
+ valuestruct = self._prefs[attr]
+ except KeyError: # unknown key, we don't care about it
+ pass
+ else:
+ if entry.value != None: # value has changed
+ newval = valuestruct.getfunc(self._gconf, self._rootkey, attr)
+ setattr( self, attr, newval)
+ else: # value has been deleted
+ setattr( self, attr, valuestruct.default )
+
+ def notify_add(self, callback):
+ """Register a callback to be called when a preference changes.
+
+ callback : a callable object which take two parameters, 'attr' the
+ name of the attribute changed and 'val' the new value.
+ """
+ self._listeners.append(callback)
+
+ def dump(self):
+ """Print all preferences.
+ """
+ for k,v in self._prefs.items():
+ print k, v.type, v.current
+
diff --git a/rapid/rapid.py b/rapid/rapid.py
new file mode 100755
index 0000000..0dcbb21
--- /dev/null
+++ b/rapid/rapid.py
@@ -0,0 +1,3050 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+#needed for python 2.5, unneeded for python 2.6
+from __future__ import with_statement
+
+import sys
+import os
+import shutil
+import time
+import datetime
+import atexit
+import tempfile
+import webbrowser
+import operator
+
+import dbus
+import dbus.bus
+import dbus.service
+from dbus.mainloop.glib import DBusGMainLoop
+DBusGMainLoop(set_as_default=True)
+
+from threading import Thread, Lock
+from thread import error as thread_error
+from thread import get_ident
+
+import gtk.gdk as gdk
+import pango
+
+try:
+ import gio
+ using_gio = True
+except ImportError:
+ import gnomevfs
+ using_gio = False
+
+
+import prefs
+import paths
+import gnomeglade
+
+from optparse import OptionParser
+
+import pynotify
+
+import ValidatedEntry
+
+import idletube as tube
+
+import config
+import common
+import misc
+import higdefaults as hd
+
+from media import getDefaultPhotoLocation
+from media import CardMedia
+
+import media
+
+import metadata
+
+import renamesubfolderprefs as rn
+
+import tableplusminus as tpm
+
+__version__ = config.version
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+except:
+ pass
+try:
+ import gtk
+ import gtk.glade
+except:
+ sys.exit(1)
+
+from common import Configi18n
+global _
+_ = Configi18n._
+
+#Translators: if neccessary, for guidance in how to translate this program, you may see http://damonlynch.net/translate.html
+PROGRAM_NAME = _('Rapid Photo Downloader')
+
+def today():
+ return datetime.date.today().strftime('%Y-%m-%d')
+
+
+
+def cmd_line(msg):
+ if verbose:
+ print msg
+
+exiting = False
+
+def updateDisplay(display_queue):
+
+ try:
+ if display_queue.size() != 0:
+ call, args = display_queue.get()
+ if not exiting:
+ call(*args)
+# else do not update display
+ else:
+ sys.stderr.write("Empty display queue!\n")
+ return True
+
+ except tube.EOInformation:
+ for w in workers.getStartedWorkers():
+ w.join()
+ gtk.main_quit()
+
+ return False
+
+
+class Queue(tube.Tube):
+ def __init__(self, maxSize = config.MAX_NO_READERS):
+ tube.Tube.__init__(self, maxSize)
+
+ def setMaxSize(self, maxSize):
+ self.maxsize = maxSize
+
+
+# Module wide values -
+# set up thesse variable in global name space, and initialize with proper
+# values later
+# this is ugly but I don't know a better way :(
+
+display_queue = Queue()
+media_collection_treeview = image_hbox = log_dialog = None
+
+
+class ThreadManager:
+ _workers = []
+
+
+ def append(self, w):
+ self._workers.append(w)
+
+ def __getitem__(self, i):
+ return self._workers[i]
+
+ def __len__(self):
+ return len(self._workers)
+
+ def disableWorker(self, thread_id):
+ """
+ set so a worker will not run, or if it is running, make it quit and therefore complete
+ """
+
+ self._workers[thread_id].manuallyDisabled = True
+ if self._workers[thread_id].hasStarted:
+ self._workers[thread_id].quit()
+
+ else:
+ self._workers[thread_id].doNotStart = True
+
+ def _isReadyToStart(self, w):
+ """
+ Returns True if the worker is ready to start
+ and has not been disabled
+ """
+ return not w.hasStarted and not w.doNotStart and not w.manuallyDisabled
+
+ def _isReadyToDownload(self, w):
+ return w.scanComplete and not w.downloadStarted and not w.doNotStart and w.isAlive() and not w.manuallyDisabled
+
+ def _isDownloading(self, w):
+ return w.downloadStarted and w.isAlive() and not w.downloadComplete
+
+ def _isFinished(self, w):
+ """
+ Returns True if the worker has finished running
+
+ It does not signify it finished a download
+ """
+
+ return (w.hasStarted and not w.isAlive()) or w.manuallyDisabled
+
+ def completedDownload(self, w):
+ return w.completedDownload
+
+ def firstWorkerReadyToStart(self):
+ for w in self._workers:
+ if self._isReadyToStart(w):
+ return w
+ return None
+
+ def firstWorkerReadyToDownload(self):
+ for w in self._workers:
+ if self._isReadyToDownload(w):
+ return w
+ return None
+
+ def startWorkers(self):
+ for w in self.getReadyToStartWorkers():
+ w.start()
+
+ def startDownloadingWorkers(self):
+ for w in self.getReadyToDownloadWorkers():
+ w.startStop()
+
+ def quitAllWorkers(self):
+ global exiting
+ exiting = True
+ for w in self._workers:
+ w.quit()
+
+ def getWorkers(self):
+ for w in self._workers:
+ yield w
+
+ def getNonFinishedWorkers(self):
+ for w in self._workers:
+ if not self._isFinished(w):
+ yield w
+
+ def getStartedWorkers(self):
+ for w in self._workers:
+ if w.hasStarted:
+ yield w
+
+ def getReadyToStartWorkers(self):
+ for w in self._workers:
+ if self._isReadyToStart(w):
+ yield w
+
+ def getReadyToDownloadWorkers(self):
+ for w in self._workers:
+ if self._isReadyToDownload(w):
+ yield w
+
+ def getNotDownloadingWorkers(self):
+ for w in self._workers:
+ if w.hasStarted and not w.downloadStarted:
+ yield w
+
+ def noReadyToStartWorkers(self):
+ n = 0
+ for w in self._workers:
+ if self._isReadyToStart(w):
+ n += 1
+ return n
+
+ def noReadyToDownloadWorkers(self):
+ n = 0
+ for w in self._workers:
+ if self._isReadyToDownload(w):
+ n += 1
+ return n
+
+ def getRunningWorkers(self):
+ for w in self._workers:
+ if w.hasStarted and w.isAlive():
+ yield w
+
+ def getDownloadingWorkers(self):
+ for w in self._workers:
+ if self._isDownloading(w):
+ yield w
+
+
+ def getPausedWorkers(self):
+ for w in self._workers:
+ if w.hasStarted and not w.running:
+ yield w
+
+ def getPausedDownloadingWorkers(self):
+ for w in self._workers:
+ if w.downloadStarted and not w.running:
+ yield w
+
+ def getFinishedWorkers(self):
+ for w in self._workers:
+ if self._isFinished(w):
+ yield w
+
+ def noDownloadingWorkers(self):
+ i = 0
+ for w in self._workers:
+ if self._isDownloading(w):
+ i += 1
+ return i
+
+ def noRunningWorkers(self):
+ i = 0
+ for w in self._workers:
+ if w.hasStarted and w.isAlive():
+ i += 1
+ return i
+
+ def getNextThread_id(self):
+ return len(self._workers)
+
+ def printWorkerStatus(self, worker=None):
+ if worker:
+ l = [worker]
+ else:
+ l = range(len(self._workers))
+ for i in l:
+ print "\nThread %i\n=======\n" % i
+ w = self._workers[i]
+ print "Volume / source:", w.cardMedia.prettyName(limit=0)
+ print "Do not start:", w.doNotStart
+ print "Started:", w.hasStarted
+ print "Running:", w.running
+ print "Scan completed:", w.scanComplete
+ print "Download started:", w.downloadStarted
+ print "Download completed:", w.downloadComplete
+ print "Finished:", self._isFinished(w)
+ print "Alive:", w.isAlive()
+ print "Manually disabled:", w.manuallyDisabled, "\n"
+
+
+
+workers = ThreadManager()
+
+class RapidPreferences(prefs.Preferences):
+ defaults = {
+ "program_version": prefs.Value(prefs.STRING, ""),
+ "download_folder": prefs.Value(prefs.STRING,
+ getDefaultPhotoLocation()),
+ "subfolder": prefs.ListValue(prefs.STRING_LIST, rn.DEFAULT_SUBFOLDER_PREFS),
+ "image_rename": prefs.ListValue(prefs.STRING_LIST, [rn.FILENAME,
+ rn.NAME_EXTENSION,
+ rn.ORIGINAL_CASE]),
+ "device_autodetection": prefs.Value(prefs.BOOL, True),
+ "device_location": prefs.Value(prefs.STRING, os.path.expanduser('~')),
+ "device_autodetection_psd": prefs.Value(prefs.BOOL, False),
+ "backup_images": prefs.Value(prefs.BOOL, False),
+ "backup_device_autodetection": prefs.Value(prefs.BOOL, True),
+ "backup_identifier": prefs.Value(prefs.STRING,
+ config.DEFAULT_BACKUP_LOCATION),
+ "backup_location": prefs.Value(prefs.STRING, os.path.expanduser('~')),
+ "strip_characters": prefs.Value(prefs.BOOL, True),
+ "auto_download_at_startup": prefs.Value(prefs.BOOL, False),
+ "auto_download_upon_device_insertion": prefs.Value(prefs.BOOL, False),
+ "auto_unmount": prefs.Value(prefs.BOOL, False),
+ "auto_exit": prefs.Value(prefs.BOOL, False),
+ "indicate_download_error": prefs.Value(prefs.BOOL, True),
+ "download_conflict_resolution": prefs.Value(prefs.STRING,
+ config.SKIP_DOWNLOAD),
+ "backup_duplicate_overwrite": prefs.Value(prefs.BOOL, False),
+ "backup_missing": prefs.Value(prefs.STRING, config.IGNORE),
+ "display_thumbnails": prefs.Value(prefs.BOOL, True),
+ "show_log_dialog": prefs.Value(prefs.BOOL, False),
+ "day_start": prefs.Value(prefs.STRING, "03:00"),
+ "downloads_today": prefs.ListValue(prefs.STRING_LIST, [today(), '0']),
+ "stored_sequence_no": prefs.Value(prefs.INT, 0),
+ }
+
+ def __init__(self):
+ prefs.Preferences.__init__(self, config.GCONF_KEY, self.defaults)
+
+ def getAndMaybeResetDownloadsToday(self):
+ v = self.getDownloadsToday()
+ if v <= 0:
+ self.resetDownloadsToday()
+ return v
+
+ def getDownloadsToday(self):
+ """Returns the preference value for the number of downloads performed today
+
+ If value is less than zero, that means the date has changed"""
+
+ hour, minute = self.getDayStart()
+ adjustedToday = datetime.datetime.strptime("%s %s:%s" % (self.downloads_today[0], hour, minute), "%Y-%m-%d %H:%M")
+
+ now = datetime.datetime.today()
+
+ if now < adjustedToday :
+ try:
+ return int(self.downloads_today[1])
+ except ValueError:
+ sys.stderr.write(_("Invalid Downloads Today value.\n"))
+ sys.stderr.write(_("Resetting value to zero.\n"))
+ self.setDownloadsToday(self.downloads_today[0] , 0)
+ return 0
+ else:
+ return -1
+
+ def setDownloadsToday(self, date, value=0):
+ self.downloads_today = [date, str(value)]
+
+ def incrementDownloadsToday(self):
+ """ returns true if day changed """
+ v = self.getDownloadsToday()
+ if v >= 0:
+ self.setDownloadsToday(self.downloads_today[0] , v + 1)
+ return False
+ else:
+ self.resetDownloadsToday(1)
+ return True
+
+ def resetDownloadsToday(self, value=0):
+ now = datetime.datetime.today()
+ hour, minute = self.getDayStart()
+ t = datetime.time(hour, minute)
+ if now.time() < t:
+ date = today()
+ else:
+ d = datetime.datetime.today() + datetime.timedelta(days=1)
+ date = d.strftime(('%Y-%m-%d'))
+
+ self.setDownloadsToday(date, value)
+
+ def setDayStart(self, hour, minute):
+ self.day_start = "%s:%s" % (hour, minute)
+
+ def getDayStart(self):
+ try:
+ t1, t2 = self.day_start.split(":")
+ return (int(t1), int(t2))
+ except ValueError:
+ sys.stderr.write(_("'Start of day' preference value is corrupted.\n"))
+ sys.stderr.write(_("Resetting to midnight.\n"))
+ self.day_start = "0:0"
+ return 0, 0
+
+
+class ImageRenameTable(tpm.TablePlusMinus):
+
+ def __init__(self, parentApp, adjustScrollWindow):
+
+ tpm.TablePlusMinus.__init__(self, 1, 3)
+ self.parentApp = parentApp
+ self.adjustScrollWindow = adjustScrollWindow
+ if adjustScrollWindow:
+ self.connect("size-request", self.size_adjustment)
+ self.connect("add", self.size_adjustment)
+ self.tableWidth = self.allocation.width
+ # vbar is '1' if there is not vertical scroll bar
+ # if there is a vertical scroll bar, then it will have a the width of the bar
+ self.vbar = self.adjustScrollWindow.get_vscrollbar().allocation.width
+
+ self.getParentAppPrefs()
+ self.getPrefsFactory()
+
+ if not hasattr(self, "errorTitle"):
+ self.errorTitle = _("Error in Image Rename preferences")
+
+ try:
+ self.prefsFactory.checkPrefsForValidity()
+
+ except (rn.PrefValueInvalidError, rn.PrefLengthError,
+ rn.PrefValueKeyComboError, rn.PrefKeyError), e:
+
+ sys.stderr.write(self.errorTitle + "\n")
+ sys.stderr.write(_("Sorry,these preferences contain an error:\n"))
+ sys.stderr.write(self.prefsFactory.formatPreferencesForPrettyPrint() + "\n")
+
+ # the preferences were invalid
+ # reset them to their default
+
+ self.prefList = self.prefsFactory.defaultPrefs
+ self.getPrefsFactory()
+ self.updateParentAppPrefs()
+
+ msg = "%s.\n" % e
+ msg += _("Resetting to default values.")
+ sys.stderr.write(msg)
+
+
+ misc.run_dialog(self.errorTitle, msg,
+ parentApp,
+ gtk.MESSAGE_ERROR)
+
+ for row in self.prefsFactory.getWidgetsBasedOnPreferences():
+ self.append(row)
+
+
+
+
+ def updatePreferences(self):
+ prefList = []
+ for row in self.pm_rows:
+ for col in range(self.pm_noColumns):
+ widget = row[col]
+ if widget:
+ name = widget.get_name()
+ if name == 'GtkComboBox':
+ value = widget.get_active_text()
+ elif name == 'GtkEntry':
+ value = widget.get_text()
+ else:
+ sys.stderr.write("Program error: Unknown preference widget!")
+ value = ''
+ else:
+ value = ''
+ prefList.append(value)
+
+ self.prefList = prefList
+ self.updateParentAppPrefs()
+ self.prefsFactory.prefList = prefList
+ self.updateExample()
+
+
+ def size_adjustment(self, arg1, arg2):
+ """ Adjust scrolledwindow width in preferences dialog to reflect width of image rename table
+
+ The algorithm is complicated by the need to tak into account the presence of a vertical scrollbar"""
+
+ if self.adjustScrollWindow:
+ if self.adjustScrollWindow.get_vscrollbar().allocation.width > 1:
+ extra = self.adjustScrollWindow.get_vscrollbar().allocation.width + 10
+ else:
+ extra = 0
+ if self.vbar <= 1:
+ if self.allocation.width > self.tableWidth:
+ self.adjustScrollWindow.set_size_request(self.allocation.width + extra, -1)
+ self.tableWidth = self.allocation.width + extra
+ elif self.allocation.width - extra > self.tableWidth:
+ self.adjustScrollWindow.set_size_request(self.allocation.width + extra, -1)
+ self.tableWidth = self.allocation.width + extra
+ self.vbar = self.adjustScrollWindow.get_vscrollbar().allocation.width
+
+ def getParentAppPrefs(self):
+ self.prefList = self.parentApp.prefs.image_rename
+
+
+
+
+ def getPrefsFactory(self):
+ self.prefsFactory = rn.ImageRenamePreferences(self.prefList, self,
+ sequences = sequences)
+
+ def updateParentAppPrefs(self):
+ self.parentApp.prefs.image_rename = self.prefList
+
+ def updateExample(self):
+ self.parentApp.updateImageRenameExample()
+
+ def getDefaultRow(self):
+ return self.prefsFactory.getDefaultRow()
+
+ def on_combobox_changed(self, widget, rowPosition):
+
+ for col in range(self.pm_noColumns):
+ if self.pm_rows[rowPosition][col] == widget:
+ break
+ selection = []
+ for i in range(col + 1):
+ # ensure it is a combo box we are getting the value from
+ w = self.pm_rows[rowPosition][i]
+ name = w.get_name()
+ if name == 'GtkComboBox':
+ selection.append(w.get_active_text())
+ else:
+ selection.append(w.get_text())
+
+ for i in range(col + 1, self.pm_noColumns):
+ selection.append('')
+
+ if col <> (self.pm_noColumns - 1):
+ widgets = self.prefsFactory.getWidgetsBasedOnUserSelection(selection)
+
+ for i in range(col + 1, self.pm_noColumns):
+ oldWidget = self.pm_rows[rowPosition][i]
+ if oldWidget:
+ self.remove(oldWidget)
+ if oldWidget in self.pm_callbacks:
+ del self.pm_callbacks[oldWidget]
+ newWidget = widgets[i]
+ self.pm_rows[rowPosition][i] = newWidget
+ if newWidget:
+ self._createCallback(newWidget, rowPosition)
+ self.attach(newWidget, i, i+1, rowPosition, rowPosition + 1)
+ newWidget.show()
+ self.updatePreferences()
+
+
+ def on_entry_changed(self, widget, rowPosition):
+ self.updatePreferences()
+
+ def on_rowAdded(self, rowPosition):
+ """
+ Update preferences, as a row has been added
+ """
+ self.updatePreferences()
+
+ # if this was the last row or 2nd to last row, and another has just been added, move vertical scrollbar down
+ if rowPosition in range(self.pm_noRows - 3, self.pm_noRows - 2):
+ adjustment = self.parentApp.rename_scrolledwindow.get_vadjustment()
+ adjustment.set_value(adjustment.upper)
+
+
+ def on_rowDeleted(self, rowPosition):
+ """
+ Update preferences, as a row has been deleted
+ """
+ self.updatePreferences()
+
+class SubfolderTable(ImageRenameTable):
+ def __init__(self, parentApp, adjustScollWindow):
+ self.errorTitle = _("Error in Download Subfolder preferences")
+ ImageRenameTable.__init__(self, parentApp, adjustScollWindow)
+
+ def getParentAppPrefs(self):
+ self.prefList = self.parentApp.prefs.subfolder
+
+ def getPrefsFactory(self):
+ self.prefsFactory = rn.SubfolderPreferences(self.prefList, self)
+
+ def updateParentAppPrefs(self):
+ self.parentApp.prefs.subfolder = self.prefList
+
+ def updateExample(self):
+ self.parentApp.updateDownloadFolderExample()
+
+
+class PreferencesDialog(gnomeglade.Component):
+ def __init__(self, parentApp):
+ gnomeglade.Component.__init__(self,
+ paths.share_dir(config.GLADE_FILE),
+ "preferencesdialog")
+
+ self.widget.set_transient_for(parentApp.widget)
+ self.prefs = parentApp.prefs
+
+ self._setupTabSelector()
+
+ self._setupControlSpacing()
+
+ # get example image data
+
+ try:
+ w = workers.firstWorkerReadyToDownload()
+ root, self.sampleImageName = w.firstImage()
+ image = os.path.join(root, self.sampleImageName)
+ self.sampleImage = metadata.MetaData(image)
+ self.sampleImage.readMetadata()
+ except:
+ self.sampleImage = metadata.DummyMetaData()
+ self.sampleImageName = 'IMG_0524.CR2'
+
+ # setup tabs
+ self._setupDownloadFolderTab()
+ self._setupImageRenameTab()
+ self._setupRenameOptionsTab()
+ self._setupDeviceTab()
+ self._setupBackupTab()
+ self._setupAutomationTab()
+ self._setupErrorTab()
+
+ self.widget.realize()
+
+ #set the width of the left column for selecting values
+ #note: this must be called after self.widget.realize(), or else the width calculation will fail
+ width_of_widest_sel_row = self.treeview.get_background_area(1, self.treeview_column)[2]
+ self.scrolled_window.set_size_request(width_of_widest_sel_row + 2, -1)
+
+ #set the minimum width of the scolled window holding the image rename table
+ if self.rename_scrolledwindow.get_vscrollbar():
+ extra = self.rename_scrolledwindow.get_vscrollbar().allocation.width + 10
+ else:
+ extra = 10
+ self.rename_scrolledwindow.set_size_request(self.rename_table.allocation.width + extra, -1)
+
+ self.widget.show()
+
+ def on_preferencesdialog_destroy(self, widget):
+ """ Delete variables from memory that cause a file descriptor to be created on a mounted media"""
+ del self.sampleImage, self.rename_table.prefsFactory, self.subfolder_table.prefsFactory
+
+ def _setupTabSelector(self):
+ self.notebook.set_show_tabs(0)
+ self.model = gtk.ListStore(type(""))
+ column = gtk.TreeViewColumn()
+ rentext = gtk.CellRendererText()
+ column.pack_start(rentext, expand=0)
+ column.set_attributes(rentext, text=0)
+ self.treeview_column = column
+ self.treeview.append_column(column)
+ self.treeview.props.model = self.model
+ for c in self.notebook.get_children():
+ label = self.notebook.get_tab_label(c).get_text()
+ if not label.startswith("_"):
+ self.model.append( (label,) )
+
+
+ # select the first value in the list store
+ self.treeview.set_cursor(0,column)
+
+ def on_download_folder_filechooser_button_selection_changed(self, widget):
+ self.prefs.download_folder = widget.get_current_folder()
+ self.updateDownloadFolderExample()
+
+ def on_backup_folder_filechooser_button_selection_changed(self, widget):
+ self.prefs.backup_location = widget.get_current_folder()
+ self.updateBackupExample()
+
+ def on_device_location_filechooser_button_selection_changed(self, widget):
+ self.prefs.device_location = widget.get_current_folder()
+
+ def _setupControlSpacing(self):
+ """
+ set spacing of some but not all controls
+
+ not currently used
+ """
+
+ self._setupTableSpacing(self.download_folder_table)
+ self.download_folder_table.set_row_spacing(2,
+ hd.VERTICAL_CONTROL_SPACE)
+ self._setupTableSpacing(self.rename_example_table)
+ self.devices_table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE)
+
+ self._setupTableSpacing(self.backup_table)
+ self.backup_table.set_col_spacing(1, hd.NESTED_CONTROLS_SPACE)
+ self.backup_table.set_col_spacing(2, hd.CONTROL_LABEL_SPACE)
+ self._setupTableSpacing(self.compatibility_table)
+ self.compatibility_table.set_row_spacing(0,
+ hd.VERTICAL_CONTROL_LABEL_SPACE)
+ self._setupTableSpacing(self.error_table)
+ self.error_table.set_row_spacing(5, hd.VERTICAL_CONTROL_SPACE / 2)
+
+
+ def _setupTableSpacing(self, table):
+ table.set_col_spacing(0, hd.NESTED_CONTROLS_SPACE)
+ table.set_col_spacing(1, hd.CONTROL_LABEL_SPACE)
+
+ def _setupSubfolderTable(self):
+ self.subfolder_table = SubfolderTable(self, None)
+ self.subfolder_vbox.pack_start(self.subfolder_table)
+ self.subfolder_table.show_all()
+
+ def _setupDownloadFolderTab(self):
+ self.download_folder_filechooser_button = gtk.FileChooserButton(
+ _("Select a folder to download photos to"))
+ self.download_folder_filechooser_button.set_current_folder(
+ self.prefs.download_folder)
+ self.download_folder_filechooser_button.set_action(
+ gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ self.download_folder_filechooser_button.connect("selection-changed",
+ self.on_download_folder_filechooser_button_selection_changed)
+
+ self.download_folder_table.attach(
+ self.download_folder_filechooser_button,
+ 2, 3, 2, 3, yoptions = gtk.SHRINK)
+ self.download_folder_filechooser_button.show()
+
+ self._setupSubfolderTable()
+ self.updateDownloadFolderExample()
+
+ def _setupImageRenameTab(self):
+
+ self.rename_table = ImageRenameTable(self, self.rename_scrolledwindow)
+ self.rename_table_vbox.pack_start(self.rename_table)
+ self.rename_table.show_all()
+ self.original_name_label.set_markup("<i>%s</i>" % self.sampleImageName)
+ self.updateImageRenameExample()
+
+ def _setupRenameOptionsTab(self):
+ self.downloads_today_entry = ValidatedEntry.ValidatedEntry(ValidatedEntry.bounded(ValidatedEntry.v_int, int, 0))
+ self.stored_number_entry = ValidatedEntry.ValidatedEntry(ValidatedEntry.bounded(ValidatedEntry.v_int, int, 1))
+ self.downloads_today_entry.connect('changed', self.on_downloads_today_entry_changed)
+ self.stored_number_entry.connect('changed', self.on_stored_number_entry_changed)
+ v = self.prefs.getAndMaybeResetDownloadsToday()
+ self.downloads_today_entry.set_text(str(v))
+ # make the displayed value of stored sequence no 1 more than actual value
+ # so as not to confuse the user
+ self.stored_number_entry.set_text(str(self.prefs.stored_sequence_no+1))
+ self.sequence_vbox.pack_start(self.downloads_today_entry, expand=True, fill=True)
+ self.sequence_vbox.pack_start(self.stored_number_entry, expand=False)
+ self.downloads_today_entry.show()
+ self.stored_number_entry.show()
+ hour, minute = self.prefs.getDayStart()
+ self.hour_spinbutton.set_value(float(hour))
+ self.minute_spinbutton.set_value(float(minute))
+
+ self.strip_characters_checkbutton.set_active(
+ self.prefs.strip_characters)
+
+ def _setupDeviceTab(self):
+ self.device_location_filechooser_button = gtk.FileChooserButton(
+ _("Select an image folder"))
+ self.device_location_filechooser_button.set_current_folder(
+ self.prefs.device_location)
+ self.device_location_filechooser_button.set_action(
+ gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
+
+ self.device_location_filechooser_button.connect("selection-changed",
+ self.on_device_location_filechooser_button_selection_changed)
+
+ self.devices2_table.attach(self.device_location_filechooser_button,
+ 1, 2, 1, 2, xoptions = gtk.EXPAND|gtk.FILL, yoptions = gtk.SHRINK)
+ self.device_location_filechooser_button.show()
+ self.autodetect_device_checkbutton.set_active(
+ self.prefs.device_autodetection)
+ self.autodetect_psd_checkbutton.set_active(
+ self.prefs.device_autodetection_psd)
+
+ self.updateDeviceControls()
+
+
+ def _setupBackupTab(self):
+ self.backup_folder_filechooser_button = gtk.FileChooserButton(
+ _("Select a folder in which to backup images"))
+ self.backup_folder_filechooser_button.set_current_folder(
+ self.prefs.backup_location)
+ self.backup_folder_filechooser_button.set_action(
+ gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
+ self.backup_folder_filechooser_button.connect("selection-changed",
+ self.on_backup_folder_filechooser_button_selection_changed)
+ self.backup_table.attach(self.backup_folder_filechooser_button,
+ 3, 4, 7, 8, yoptions = gtk.SHRINK)
+ self.backup_folder_filechooser_button.show()
+ self.backup_identifier_entry.set_text(self.prefs.backup_identifier)
+
+ #setup controls for manipulating sensitivity
+ self._backupControls0 = [self.auto_detect_backup_checkbutton,
+ self.missing_backup_label,
+ self.backup_error_radiobutton,
+ self.backup_warning_radiobutton,
+ self.backup_ignore_radiobutton]
+ self._backupControls1 = [self.backup_identifier_explanation_label,
+ self.backup_identifier_label,
+ self.backup_identifier_entry,
+ self.example_backup_path_label,
+ self.backup_example_label,]
+ self._backupControls2 = [self.backup_location_label,
+ self.backup_folder_filechooser_button,
+ self.backup_location_explanation_label]
+ self._backupControls = self._backupControls0 + self._backupControls1 + \
+ self._backupControls2
+
+ #assign values to checkbuttons only when other controls
+ #have been setup, because their toggle signal is activated
+ #when a value is assigned
+
+ self.backup_checkbutton.set_active(self.prefs.backup_images)
+ self.auto_detect_backup_checkbutton.set_active(
+ self.prefs.backup_device_autodetection)
+ self.updateBackupControls()
+ self.updateBackupExample()
+
+ def _setupAutomationTab(self):
+ self.auto_startup_checkbutton.set_active(
+ self.prefs.auto_download_at_startup)
+ self.auto_insertion_checkbutton.set_active(
+ self.prefs.auto_download_upon_device_insertion)
+ self.auto_unmount_checkbutton.set_active(
+ self.prefs.auto_unmount)
+ self.auto_exit_checkbutton.set_active(
+ self.prefs.auto_exit)
+
+
+ def _setupErrorTab(self):
+ self.indicate_download_error_checkbutton.set_active(
+ self.prefs.indicate_download_error)
+
+ if self.prefs.download_conflict_resolution == config.SKIP_DOWNLOAD:
+ self.skip_download_radiobutton.set_active(True)
+ else:
+ self.add_identifier_radiobutton.set_active(True)
+
+ if self.prefs.backup_missing == config.REPORT_ERROR:
+ self.backup_error_radiobutton.set_active(True)
+ elif self.prefs.backup_missing == config.REPORT_WARNING:
+ self.backup_warning_radiobutton.set_active(True)
+ else:
+ self.backup_ignore_radiobutton.set_active(True)
+
+ if self.prefs.backup_duplicate_overwrite:
+ self.backup_duplicate_overwrite_radiobutton.set_active(True)
+ else:
+ self.backup_duplicate_skip_radiobutton.set_active(True)
+
+ def updateImageRenameExample(self):
+ """
+ Displays example image name to the user
+ """
+
+ if hasattr(self, 'rename_table'):
+ name, problem = self.rename_table.prefsFactory.generateNameUsingPreferences(
+ self.sampleImage, self.sampleImageName,
+ self.prefs.strip_characters, sequencesPreliminary=False)
+ else:
+ name = problem = ''
+
+ # since this is markup, escape it
+ text = "<i>%s</i>" % common.escape(name)
+
+ if problem:
+ text += "\n"
+ # Translators: please do not modify or leave out html formatting tags like <i> and <b>. These are used to format the text the users sees
+ text += _("<i><b>Warning:</b> There is insufficient image metatdata to fully generate the name. Please use other renaming options.</i>")
+
+ self.new_name_label.set_markup(text)
+
+ def updateDownloadFolderExample(self):
+ """
+ Displays example subfolder name(s) to the user
+ """
+
+ if hasattr(self, 'subfolder_table'):
+ path, problem = self.subfolder_table.prefsFactory.generateNameUsingPreferences(
+ self.sampleImage, self.sampleImageName,
+ self.prefs.strip_characters)
+ else:
+ path = problem = ''
+
+ text = os.path.join(self.prefs.download_folder, path)
+ # since this is markup, escape it
+ path = common.escape(text)
+ if problem:
+ warning = _("<i><b>Warning:</b> There is insufficient image metatdata to fully generate subfolders. Please use other subfolder naming options.</i>" )
+ else:
+ warning = ""
+ # Translators: you should not modify or leave out the %s. This is a code used by the programming language python to insert a value that thes user will see
+ self.example_download_path_label.set_markup(_("<i>Example: %s</i>") % text)
+ self.subfolder_warning_label.set_markup(warning)
+
+ def on_hour_spinbutton_value_changed(self, spinbutton):
+ hour = spinbutton.get_value_as_int()
+ minute = self.minute_spinbutton.get_value_as_int()
+ self.prefs.setDayStart(hour, minute)
+ self.on_downloads_today_entry_changed(self.downloads_today_entry)
+
+ def on_minute_spinbutton_value_changed(self, spinbutton):
+ hour = self.hour_spinbutton.get_value_as_int()
+ minute = spinbutton.get_value_as_int()
+ self.prefs.setDayStart(hour, minute)
+ self.on_downloads_today_entry_changed(self.downloads_today_entry)
+
+ def on_downloads_today_entry_changed(self, entry):
+ if workers.noRunningWorkers() == 0:
+ # do not update value if a download is occurring - it will mess it up!
+ v = entry.get_text()
+ try:
+ v = int(v)
+ except:
+ v = 0
+ if v < 0:
+ v = 0
+ self.prefs.resetDownloadsToday(v)
+ sequences.setDownloadsToday(v)
+ self.updateImageRenameExample()
+
+ def on_stored_number_entry_changed(self, entry):
+ if workers.noRunningWorkers() == 0:
+ # do not update value if a download is occurring - it will mess it up!
+ v = entry.get_text()
+ try:
+ # the displayed value of stored sequence no 1 more than actual value
+ # so as not to confuse the user
+ v = int(v) - 1
+ except:
+ v = 0
+ if v < 0:
+ v = 0
+ self.prefs.stored_sequence_no = v
+ sequences.setStoredSequenceNo(v)
+ self.updateImageRenameExample()
+
+ def on_response(self, dialog, arg):
+ if arg == gtk.RESPONSE_HELP:
+ webbrowser.open("http://www.damonlynch.net/rapid/documentation")
+ else:
+ # arg==gtk.RESPONSE_CLOSE, or the user hit the 'x' to close the window
+ self.prefs.backup_identifier = self.backup_identifier_entry.get_property("text")
+
+ #check subfolder preferences for bad values
+ filtered, prefList = rn.filterSubfolderPreferences(self.prefs.subfolder)
+ if filtered:
+ cmd_line(_("The subfolder preferences had some unnecessary values removed."))
+ if prefList:
+ self.prefs.subfolder = prefList
+ else:
+ #Preferences list is now empty
+ msg = _("The subfolder preferences entered are invalid and cannot be used.\nThey will be reset to their default values.")
+ sys.stderr.write(msg + "\n")
+ misc.run_dialog(PROGRAM_NAME, msg)
+ self.prefs.subfolder = self.prefs.get_default("subfolder")
+
+ self.widget.destroy()
+
+
+ def on_auto_startup_checkbutton_toggled(self, checkbutton):
+ self.prefs.auto_download_at_startup = checkbutton.get_active()
+
+ def on_auto_insertion_checkbutton_toggled(self, checkbutton):
+ self.prefs.auto_download_upon_device_insertion = checkbutton.get_active()
+
+ def on_auto_unmount_checkbutton_toggled(self, checkbutton):
+ self.prefs.auto_unmount = checkbutton.get_active()
+
+ def on_auto_exit_checkbutton_toggled(self, checkbutton):
+ self.prefs.auto_exit = checkbutton.get_active()
+
+ def on_autodetect_device_checkbutton_toggled(self, checkbutton):
+ self.prefs.device_autodetection = checkbutton.get_active()
+ self.updateDeviceControls()
+
+ def on_autodetect_psd_checkbutton_toggled(self, checkbutton):
+ self.prefs.device_autodetection_psd = checkbutton.get_active()
+
+ def on_backup_duplicate_overwrite_radiobutton_toggled(self, widget):
+ self.prefs.backup_duplicate_overwrite = widget.get_active()
+
+ def on_backup_duplicate_skip_radiobutton_toggled(self, widget):
+ self.prefs.backup_duplicate_overwrite = not widget.get_active()
+
+ def on_backup_error_radiobutton_toggled(self, widget):
+ self.prefs.backup_missing = config.REPORT_ERROR
+
+ def on_backup_warning_radiobutton_toggled(self, widget):
+ self.prefs.backup_missing = config.REPORT_WARNING
+
+ def on_backup_ignore_radiobutton_toggled(self, widget):
+ self.prefs.backup_missing = config.IGNORE
+
+ def on_treeview_cursor_changed(self, tree):
+ path, column = tree.get_cursor()
+ self.notebook.set_current_page(path[0])
+
+
+ def on_strip_characters_checkbutton_toggled(self, check_button):
+ self.prefs.strip_characters = check_button.get_active()
+ self.updateImageRenameExample()
+ self.updateDownloadFolderExample()
+
+ def on_indicate_download_error_checkbutton_toggled(self, check_button):
+ self.prefs.indicate_download_error = check_button.get_active()
+
+ def on_add_identifier_radiobutton_toggled(self, widget):
+ if widget.get_active():
+ self.prefs.download_conflict_resolution = config.ADD_UNIQUE_IDENTIFIER
+ else:
+ self.prefs.download_conflict_resolution = config.SKIP_DOWNLOAD
+
+
+ def updateDeviceControls(self):
+ """
+ Sets sensitivity of image device controls
+ """
+ controls = [self.device_location_explanation_label,
+ self.device_location_label,
+ self.device_location_filechooser_button]
+
+ if self.prefs.device_autodetection:
+ for c in controls:
+ c.set_sensitive(False)
+ self.autodetect_psd_checkbutton.set_sensitive(True)
+ self.autodetect_image_devices_label.set_sensitive(True)
+ else:
+ for c in controls:
+ c.set_sensitive(True)
+ self.autodetect_psd_checkbutton.set_sensitive(False)
+ self.autodetect_image_devices_label.set_sensitive(False)
+
+ def updateBackupControls(self):
+ """
+ Sets sensitivity of backup related widgets
+ """
+
+ if not self.backup_checkbutton.get_active():
+ for c in self._backupControls:
+ c.set_sensitive(False)
+
+ else:
+ for c in self._backupControls0:
+ c.set_sensitive(True)
+
+ self.updateBackupControlsAuto()
+
+ def updateBackupControlsAuto(self):
+ """
+ Sets sensitivity of subset of backup related widgets
+ """
+
+ if self.auto_detect_backup_checkbutton.get_active():
+ for c in self._backupControls1:
+ c.set_sensitive(True)
+ for c in self._backupControls2:
+ c.set_sensitive(False)
+ else:
+ for c in self._backupControls1:
+ c.set_sensitive(False)
+ for c in self._backupControls2:
+ c.set_sensitive(True)
+
+ def on_auto_detect_backup_checkbutton_toggled(self, widget):
+ self.prefs.backup_device_autodetection = widget.get_active()
+ self.updateBackupControlsAuto()
+
+ def on_backup_checkbutton_toggled(self, widget):
+ self.prefs.backup_images = self.backup_checkbutton.get_active()
+ self.updateBackupControls()
+
+ def on_backup_identifier_entry_changed(self, widget):
+ self.updateBackupExample()
+
+ def on_backup_scan_folder_on_entry_changed(self, widget):
+ self.updateBackupExample()
+
+ def updateBackupExample(self):
+ # Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+ path = os.path.join(config.MEDIA_LOCATION, _("externaldrive1"))
+ # Translators: this value is used as an example device when automatic backup device detection is enabled. You should translate this.
+ path2 = os.path.join(config.MEDIA_LOCATION, _("externaldrive2"))
+
+ path = os.path.join(path, self.backup_identifier_entry.get_text())
+ path2 = os.path.join(path2, self.backup_identifier_entry.get_text())
+ path = common.escape(path)
+ path2 = common.escape(path2)
+ self.example_backup_path_label.set_markup("<i>%s</i>\n<i>%s</i>" % (path,
+ path2))
+
+
+
+
+class CopyPhotos(Thread):
+ """Copies photos from source to destination, backing up if needed"""
+ def __init__(self, thread_id, parentApp, fileRenameLock, fileSequenceLock, statsLock, downloadStats, autoStart = False, cardMedia = None):
+ self.parentApp = parentApp
+ self.thread_id = thread_id
+ self.ctrl = True
+ self.running = False
+ self.manuallyDisabled = False
+ # enable the capacity to block oneself with a lock
+ # the lock will be first set when the thread begins
+ # it will then be locked when the thread needs to be paused
+ # releasing it will cause the code to restart from where it
+ # left off
+ self.lock = Lock()
+
+ self.fileRenameLock = fileRenameLock
+ self.fileSequenceLock = fileSequenceLock
+ self.statsLock = statsLock
+
+ self.downloadStats = downloadStats
+
+ self.hasStarted = False
+ self.doNotStart = False
+
+ self.autoStart = autoStart
+ self.cardMedia = cardMedia
+
+ self.initializeDisplay(thread_id, self.cardMedia)
+
+ self.noErrors = self.noWarnings = 0
+
+ self.scanComplete = self.downloadStarted = self.downloadComplete = False
+
+ Thread.__init__(self)
+
+
+ def initializeDisplay(self, thread_id, cardMedia = None):
+
+ if self.cardMedia:
+ media_collection_treeview.addCard(thread_id, self.cardMedia.prettyName(),
+ '', 0, progress=0.0,
+ # This refers to when a device like a hard drive is having its contents scanned,
+ # looking for images. It is visible initially in the progress bar for each device
+ # (which normally holds "x of y images copied").
+ # It maybe displayed only briefly if the contents of the device being scanned is small.
+ progressBarText=_('scanning...'))
+
+
+ def firstImage(self):
+ """
+ returns name, path and size of the first image
+ """
+ name, root, size, modificationTime = self.cardMedia.firstImage()
+ return root, name
+
+ def handlePreferencesError(self, e, prefsFactory):
+ sys.stderr.write(_("Sorry,these preferences contain an error:\n"))
+ sys.stderr.write(prefsFactory.formatPreferencesForPrettyPrint() + "\n")
+ msg = str(e)
+ sys.stderr.write(msg + "\n")
+
+ def initializeFromPrefs(self, notifyOnError):
+ """
+ Setup thread so that user preferences are handled
+ """
+ self.prefs = self.parentApp.prefs
+
+ self.imageRenamePrefsFactory = rn.ImageRenamePreferences(self.prefs.image_rename, self,
+ self.fileSequenceLock, sequences)
+ try:
+ self.imageRenamePrefsFactory.checkPrefsForValidity()
+ except (rn.PrefValueInvalidError, rn.PrefLengthError,
+ rn.PrefValueKeyComboError, rn.PrefKeyError), e:
+ if notifyOnError:
+ self.handlePreferencesError(e, self.imageRenamePrefsFactory)
+ raise rn.PrefError
+
+
+ self.subfolderPrefsFactory = rn.SubfolderPreferences(
+ self.prefs.subfolder, self)
+ try:
+ self.subfolderPrefsFactory.checkPrefsForValidity()
+ except (rn.PrefValueInvalidError, rn.PrefLengthError,
+ rn.PrefValueKeyComboError, rn.PrefKeyError), e:
+ if notifyOnError:
+ self.handlePreferencesError(e, self.subfolderPrefsFactory)
+ raise rn.PrefError
+
+ # copy this variable, as it is used heavily in the loop
+ # and it is perhaps relatively expensive to read
+ self.stripCharacters = self.prefs.strip_characters
+
+
+ def run(self):
+ """
+ Copy photos from device to local drive, and if requested, backup
+
+ 1. Should the image be downloaded?
+ 1.a generate file name
+ 1.a.1 generate sequence numbers if needed
+ 1.a.2 FIFO queue sequence numbers to indicate that they could
+ potentially be used in a filename
+ 1.b check to see if a file exists with the same name in the place it will
+ be downloaded to
+ 1.c if it exisits, and unique identifiers are not being used:
+ 1.b.1 if using sequence numbers or letters, then potentially any of the
+ sequence numbers in the queue could be used to make the filename
+ 1.b.1.a generate and check each filename using sequence numbers in the queue
+ 1.b.1.b if one of these filenames is unique, then image needs to be downloaded
+ 1.b.2 do not do not download
+
+
+ 2. Download the image
+ 2.a copy it to temporary folder (this takes time)
+ 2.b is the file name still unique? Perhaps a new file was created with this name in the meantime
+ (either by another thread or another program)
+ 2.b.1 don't allow any other thread to rename a file
+ 2.b.2 check file name
+ 2.b.3 adding suffix if it is not unique, being careful not to overwrite any existing file with a suffix
+ 2.b.4 rename it to the "real"" name, effectively performing a mv
+ 2.b.5 allow other threads to rename files
+
+ 3. Backup the image, using the same filename as was used when it was downloaded
+ 3.a does a file with the same name already exist on the backup medium?
+ 3.b if so, user preferences determine whether it should be overwritten or not
+ """
+
+ def getPrefs(notifyOnError):
+ try:
+ self.initializeFromPrefs(notifyOnError)
+ return True
+ except rn.PrefError:
+ if notifyOnError:
+ display_queue.put((media_collection_treeview.removeCard, (self.thread_id, )))
+ msg = _("There is an error in the program preferences.")
+ msg += _("\nPlease check preferences, restart the program, and try again.")
+ logError(config.CRITICAL_ERROR, _("Download cannot proceed"), msg)
+ cmd_line(_("Download cannot proceed"))
+ cmd_line(msg)
+ return False
+ def scanMedia():
+
+ images = []
+ imageSizeSum = 0
+ for root, dirs, files in os.walk(self.cardMedia.getPath()):
+ for name in files:
+ if not self.running:
+ self.lock.acquire()
+ self.running = True
+
+ if not self.ctrl:
+ self.running = False
+ display_queue.put((media_collection_treeview.removeCard, (self.thread_id, )))
+ display_queue.close("rw")
+ return
+
+ if media.isImage(name):
+ image = os.path.join(root, name)
+ size = os.path.getsize(image)
+ modificationTime = os.path.getmtime(image)
+ images.append((name, root, size, modificationTime),)
+ imageSizeSum += size
+ images.sort(key=operator.itemgetter(3))
+ noImages = len(images)
+
+ self.scanComplete = True
+
+ if noImages:
+ self.cardMedia.setMedia(images, imageSizeSum, noImages)
+ # Translators: as already, mentioned the %s value should not be modified or left out. It may be moved if necessary.
+ # It refers to the actual number of images that can be copied. For example, the user might see the following:
+ # '0 of 512 images copied'.
+ # This particular text is displayed to the user before the download has started.
+ display = _("0 of %s images copied") % noImages
+ display_queue.put((media_collection_treeview.updateCard, (self.thread_id, self.cardMedia.sizeOfImages(), noImages)))
+ display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, 0.0, display, 0)))
+ display_queue.put((self.parentApp.timeRemaining.add, (self.thread_id, imageSizeSum)))
+ display_queue.put((self.parentApp.setDownloadButtonSensitivity, ()))
+
+ # Translators: as you have already seen, the text can contain values that should not be modified or left out by you, for example %s.
+ # This text is another example of that, but it is is a little more complex. Here there are two values which will be displayed
+ # to the user when they run the program, signifying the number of images found, and the device they were found on.
+ # %(number)s should be left exactly as is: 'number' should not be translated. The same applies to %(device)s: 'device' should
+ # not be translated. Generally speaking, if translating the sentence requires it, you can move items like '%(xyz)s' around
+ # in a sentence, but you should never modify them or leave them out.
+ cmd_line(_("Device scan complete: found %(number)s images on %(device)s") %
+ {'number': noImages, 'device': self.cardMedia.prettyName(limit=0)})
+ return True
+ else:
+ # it might be better to display "0 of 0" here
+ display_queue.put((media_collection_treeview.removeCard, (self.thread_id, )))
+ cmd_line(_("Device scan complete: no images found on %s") % self.cardMedia.prettyName(limit=0))
+ return False
+
+ def cleanUp():
+ """
+ Cleanup functions that must be performed whether the thread exits
+ early or when it has completed its run.
+ """
+
+ # possibly delete any lingering files
+ tf = os.listdir(tempWorkingDir)
+ if tf:
+ for f in tf:
+ os.remove(os.path.join(tempWorkingDir, f))
+
+ os.rmdir(tempWorkingDir)
+
+
+ def logError(severity, problem, details, resolution=None):
+ display_queue.put((log_dialog.addMessage, (self.thread_id, severity, problem, details,
+ resolution)))
+ if severity == config.WARNING:
+ self.noWarnings += 1
+ else:
+ self.noErrors += 1
+
+
+ def checkProblemWithImageNameGeneration(newName, image, problem):
+ if not newName:
+ # a serious problem - a filename should never be blank!
+ logError(config.SERIOUS_ERROR,
+ _("Image filename could not be generated"),
+ # '%(source)s' and '%(problem)s' are two more examples of text that should not be modified or left out
+ _("Source: %(source)s\nProblem: %(problem)s") % {'source': image, 'problem': problem},
+ IMAGE_SKIPPED)
+ elif problem:
+ logError(config.WARNING,
+ _("Image filename could not be properly generated. Check to ensure there is sufficient image metadata."),
+ _("Source: %(source)s\nDestination: %(destination)s\nProblem: %(problem)s") %
+ {'source': image, 'destination': newName, 'problem': problem})
+
+ def generateSubfolderAndFileName(image, name, needMetaDataToCreateUniqueImageName,
+ needMetaDataToCreateUniqueSubfolderName):
+ skipImage = False
+ try:
+ imageMetadata = metadata.MetaData(image)
+ except IOError:
+ logError(config.CRITICAL_ERROR, _("Could not open image"),
+ _("Source: %s") % image,
+ IMAGE_SKIPPED)
+ skipImage = True
+ imageMetadata = newName = newFile = path = subfolder = None
+ else:
+ imageMetadata.readMetadata()
+ if not imageMetadata.exifKeys() and (needMetaDataToCreateUniqueSubfolderName or
+ (needMetaDataToCreateUniqueImageName and
+ not addUniqueIdentifier)):
+ logError(config.SERIOUS_ERROR, _("Image has no metadata"),
+ _("Metadata is essential for generating subfolders / image names.\nSource: %s") % image,
+ IMAGE_SKIPPED)
+ skipImage = True
+ newName = newFile = path = subfolder = None
+
+ else:
+ subfolder, problem = self.subfolderPrefsFactory.generateNameUsingPreferences(
+ imageMetadata, name,
+ self.stripCharacters)
+
+ if problem:
+ logError(config.WARNING,
+ _("Subfolder name could not be properly generated. Check to ensure there is sufficient image metadata."),
+ _("Subfolder: %(subfolder)s\nImage: %(image)s\nProblem: %(problem)s") %
+ {'subfolder': subfolder, 'image': image, 'problem': problem})
+
+ # pass the subfolder the image will go into, as this is needed to determine subfolder sequence numbers
+ # indicate that sequences chosen should be queued
+
+ newName, problem = self.imageRenamePrefsFactory.generateNameUsingPreferences(
+ imageMetadata, name, self.stripCharacters, subfolder,
+ sequencesPreliminary = True)
+
+ path = os.path.join(baseDownloadDir, subfolder)
+ newFile = os.path.join(path, newName)
+
+ if not newName:
+ skipImage = True
+ checkProblemWithImageNameGeneration(newName, image, problem)
+
+ return (skipImage, imageMetadata, newName, newFile, path, subfolder)
+
+ def downloadImage(path, newFile, newName, originalName, image, imageMetadata, subfolder):
+ try:
+ imageDownloaded = False
+ if not os.path.isdir(path):
+ os.makedirs(path)
+
+ nameUniqueBeforeCopy = True
+ downloadNonUniqueFile = True
+
+
+ # do a preliminary check to see if a file with the same name already exists
+ if os.path.exists(newFile):
+ nameUniqueBeforeCopy = False
+ if not addUniqueIdentifier:
+ downloadNonUniqueFile = False
+ if usesSequenceElements:
+ # potentially, a unique image name could still be generated
+ # investigate this possibility
+ with self.fileSequenceLock:
+ for possibleName, problem in self.imageRenamePrefsFactory.generateNameSequencePossibilities(imageMetadata,
+ originalName, self.stripCharacters, subfolder):
+# print "checking", possibleName, "using", originalName
+ if possibleName:
+ # no need to check for any problems here, it's just a temporary name
+ possibleFile = os.path.join(path, possibleName)
+ possibleTempFile = os.path.join(tempWorkingDir, possibleName)
+ if not os.path.exists(possibleFile) and not os.path.exists(possibleTempFile):
+ downloadNonUniqueFile = True
+ break
+
+
+ if self.prefs.indicate_download_error and not downloadNonUniqueFile:
+ logError(config.SERIOUS_ERROR, IMAGE_ALREADY_EXISTS,
+ _("Source: %(source)s\nDestination: %(destination)s") %
+ {'source': image, 'destination': newFile},
+ IMAGE_SKIPPED)
+
+ if nameUniqueBeforeCopy or downloadNonUniqueFile:
+ tempWorkingfile = os.path.join(tempWorkingDir, newName)
+ shutil.copy2(image, tempWorkingfile)
+
+ with self.fileRenameLock:
+ doRename = True
+ if usesSequenceElements:
+ with self.fileSequenceLock:
+ # get a filename and use this as the "real" filename
+ newName, problem = self.imageRenamePrefsFactory.generateNameUsingPreferences(
+ imageMetadata, originalName, self.stripCharacters, subfolder,
+ sequencesPreliminary = False)
+ checkProblemWithImageNameGeneration(newName, image, problem)
+ if not newName:
+ # there was a serious error generating the filename
+ doRename = False
+ else:
+ newFile = os.path.join(path, newName)
+ # check if the file exists again
+ if os.path.exists(newFile):
+ if not addUniqueIdentifier:
+ doRename = False
+ if self.prefs.indicate_download_error:
+ logError(config.SERIOUS_ERROR, IMAGE_ALREADY_EXISTS,
+ _("Source: %(source)s\nDestination: %(destination)s")
+ % {'source': image, 'destination': newFile},
+ IMAGE_SKIPPED)
+ else:
+ # add basic suffix to make the filename unique
+ name = os.path.splitext(newName)
+ suffixAlreadyUsed = True
+ while suffixAlreadyUsed:
+ if newFile in duplicate_files:
+ duplicate_files[newFile] += 1
+ else:
+ duplicate_files[newFile] = 1
+ identifier = '_%s' % duplicate_files[newFile]
+ newName = name[0] + identifier + name[1]
+ possibleNewFile = os.path.join(path, newName)
+ suffixAlreadyUsed = os.path.exists(possibleNewFile)
+
+ if self.prefs.indicate_download_error:
+ logError(config.SERIOUS_ERROR, IMAGE_ALREADY_EXISTS,
+ _("Source: %(source)s\nDestination: %(destination)s")
+ % {'source': image, 'destination': newFile},
+ _("Unique identifier '%s' added") % identifier)
+
+ newFile = possibleNewFile
+
+
+ if doRename:
+ os.rename(tempWorkingfile, newFile)
+ imageDownloaded = True
+ if usesSequenceElements:
+ with self.fileSequenceLock:
+ self.imageRenamePrefsFactory.sequences.imageCopySucceeded()
+ if usesStoredSequenceNo:
+ self.prefs.stored_sequence_no += 1
+
+ with self.fileSequenceLock:
+ if self.prefs.incrementDownloadsToday():
+ # A new day, according the user's preferences of what time a day begins, has started
+ cmd_line(_("New day has started - resetting 'Downloads Today' sequence number"))
+
+ sequences.setDownloadsToday(0)
+
+ except IOError, (errno, strerror):
+ logError(config.SERIOUS_ERROR, _('Download copying error'),
+ _("Source: %(source)s\nDestination: %(destination)s\nError: %(errorno)s %(strerror)s")
+ % {'source': image, 'destination': newFile, 'errorno': errno, 'strerror': strerror},
+ _('The image was not copied.'))
+
+ except OSError, (errno, strerror):
+ logError(config.CRITICAL_ERROR, _('Download copying error'),
+ "Source: %(source)s\nDestination: %(destination)s\nError: %(errorno)s %(strerror)s"
+ % {'source': image, 'destination': newFile, 'errorno': errno, 'strerror': strerror},
+ )
+
+ if usesSequenceElements:
+ if not imageDownloaded:
+ self.imageRenamePrefsFactory.sequences.imageCopyFailed()
+
+ return (imageDownloaded, newName, newFile)
+
+
+ def backupImage(subfolder, newName, imageDownloaded, newFile, image):
+ """ backup image to path(s) chosen by the user
+
+ there are two scenarios:
+ (1) image has just been downloaded and should now be backed up
+ (2) image was already downloaded on some previous occassion and should still be backed up, because it hasn't been yet
+ (3) image has been backed up already (or at least, a file with the same name already exists)
+ """
+
+ try:
+ for backupDir in self.parentApp.backupVolumes:
+ backupPath = os.path.join(backupDir, subfolder)
+ newBackupFile = os.path.join(backupPath, newName)
+ copyBackup = True
+ if os.path.exists(newBackupFile):
+ # again, not thread safe
+ copyBackup = self.prefs.backup_duplicate_overwrite
+ if self.prefs.indicate_download_error:
+ severity = config.SERIOUS_ERROR
+ problem = _("Backup image already exists")
+ details = _("Source: %(source)s\nDestination: %(destination)s") \
+ % {'source': image, 'destination': newBackupFile}
+ if copyBackup :
+ resolution = IMAGE_OVERWRITTEN
+ else:
+ resolution = IMAGE_SKIPPED
+ logError(severity, problem, details, resolution)
+
+ if copyBackup:
+ if imageDownloaded:
+ fileToCopy = newFile
+ else:
+ fileToCopy = image
+ if not os.path.isdir(backupPath):
+ # recreate folder structure in backup location
+ # cannot do os.makedirs(backupPath) - it gives bad results when using external drives
+ # we know backupDir exists
+ # all the components of subfolder may not
+ folders = subfolder.split(os.path.sep)
+ folderToMake = backupDir
+ for f in folders:
+ if f:
+ folderToMake = os.path.join(folderToMake, f)
+ if not os.path.isdir(folderToMake):
+ try:
+ os.mkdir(folderToMake)
+ except (errno, strerror):
+ logError(config.SERIOUS_ERROR, _('Backing up error'),
+ _("Destination directory could not be created\n%(directory)s\nError: %(errno)s %(strerror)s")
+ % {'directory': folderToMake, 'errno': errno, 'strerror': strerror},
+ )
+
+ shutil.copy2(fileToCopy, newBackupFile)
+
+ except IOError, (errno, strerror):
+ logError(config.SERIOUS_ERROR, _('Backing up error'),
+ _("Source: %(source)s\nDestination: %(destination)s\nError: %(errno)s %(strerror)s")
+ % {'source': image, 'destination': newBackupFile, 'errno': errno, 'strerror': strerror},
+ _('The image was not copied.'))
+
+ except OSError, (errno, strerror):
+ logError(config.CRITICAL_ERROR, _('Backing up error'),
+ _("Source: %(source)s\nDestination: %(destination)s\nError: %(errno)s %(strerror)s")
+ % {'source': image, 'destination': newBackupFile, 'errno': errno, 'strerror': strerror}
+ )
+
+ def notifyAndUnmount():
+ if not self.cardMedia.volume:
+ unmountMessage = ""
+ notificationName = PROGRAM_NAME
+ else:
+ notificationName = self.cardMedia.volume.get_name()
+ if self.prefs.auto_unmount:
+ self.cardMedia.volume.unmount(self.on_volume_unmount)
+ # This message informs the user that the device (e.g. camera, hard drive or memory card) was automatically unmounted and they can now remove it
+ unmountMessage = _("The device can now be safely removed")
+ else:
+ unmountMessage = ""
+
+ message = _("%s images downloaded") % noImagesDownloaded
+ if noImagesSkipped:
+ message += "\n" + _("%s images skipped") % noImagesSkipped
+
+ if unmountMessage:
+ message = "%s\n%s" % (message, unmountMessage)
+
+ if self.noWarnings:
+ message = "%s\n%s " % (message, self.noWarnings) + _("warnings")
+ if self.noErrors:
+ message = "%s\n%s " % (message, self.noErrors) + _("errors")
+
+ n = pynotify.Notification(notificationName, message)
+ n.show()
+
+
+
+
+ self.hasStarted = True
+ display_queue.open('w')
+
+ #Do not try to handle any preference errors here
+ getPrefs(False)
+
+ #check for presence of backup meditum
+ if self.prefs.backup_images:
+ if self.prefs.backup_missing <> config.IGNORE:
+ if not len(self.parentApp.backupVolumes):
+ if self.prefs.backup_missing == config.REPORT_ERROR:
+ e = config.SERIOUS_ERROR
+ else:
+ e = config.WARNING
+ logError(e, _("Backup device missing"), _("No backup device was detected."))
+
+
+ if not scanMedia():
+ cmd_line(_("This device has no images to download from."))
+ display_queue.close("rw")
+ self.running = False
+ self.lock.release()
+ return
+ elif not self.autoStart:
+ # halt thread, waiting to be restarted so download proceeds
+ self.running = False
+ self.lock.acquire()
+
+ if not self.ctrl:
+ # thread will restart at this point, when the program is exiting
+ # so must exit if self.ctrl indicates this
+
+ self.running = False
+ display_queue.close("rw")
+ return
+
+ self.running = True
+
+ if not getPrefs(True):
+ self.running = False
+ display_queue.close("rw")
+ return
+
+ self.downloadStarted = True
+ cmd_line(_("Download has started from %s") % self.cardMedia.prettyName(limit=0))
+
+ # Some images may not have metadata (this
+ # is unlikely for images straight out of a
+ # camera, but it is possible for images that have been edited). If
+ # only non-dynamic components make up the rest of an image name
+ # (e.g. text specified by the user), then relying on metadata will
+ # likely produce duplicate names.
+
+ needMetaDataToCreateUniqueImageName = self.imageRenamePrefsFactory.needImageMetaDataToCreateUniqueName()
+
+ # subfolder generation also need to be examined, but here the need is
+ # not so exacting, since subfolders contain images, and naturally the
+ # requirement to be unique is far more relaxed. However if subfolder
+ # generation relies entirely on metadata, that is a problem worth
+ # looking for
+ needMetaDataToCreateUniqueSubfolderName = self.subfolderPrefsFactory.needMetaDataToCreateUniqueName()
+
+ i = 0
+ sizeDownloaded = noImagesDownloaded = noImagesSkipped = 0
+
+ sizeImages = self.cardMedia.sizeOfImages(humanReadable = False)
+ display_queue.put((self.parentApp.addToTotalDownloadSize, (sizeImages, )))
+ display_queue.put((self.parentApp.setOverallDownloadMark, ()))
+ display_queue.put((self.parentApp.postStartDownloadTasks, ()))
+
+ sizeImages = float(sizeImages)
+ noImages = self.cardMedia.numberOfImages()
+
+ baseDownloadDir = self.prefs.download_folder
+ #create a temporary directory in which to download the photos to
+ #don't want to put it in system temp folder, as that is likely
+ #to be on another partition and hence copying files from it
+ #to the download folder will be slow!
+ tempWorkingDir = tempfile.mkdtemp(prefix='rapid-tmp-',
+ dir=baseDownloadDir)
+
+ IMAGE_SKIPPED = _("Image skipped")
+ IMAGE_OVERWRITTEN = _("Image overwritten")
+ IMAGE_ALREADY_EXISTS = _("Image already exists")
+
+ addUniqueIdentifier = self.prefs.download_conflict_resolution == config.ADD_UNIQUE_IDENTIFIER
+ usesSequenceElements = self.imageRenamePrefsFactory.usesSequenceElements()
+ usesStoredSequenceNo = self.imageRenamePrefsFactory.usesTheSequenceElement(rn.STORED_SEQ_NUMBER)
+ sequences. setUseOfSequenceElements(
+ self.imageRenamePrefsFactory.usesTheSequenceElement(rn.SESSION_SEQ_NUMBER),
+ self.imageRenamePrefsFactory.usesTheSequenceElement(rn.SEQUENCE_LETTER))
+
+
+ while i < noImages:
+ if not self.running:
+ self.lock.acquire()
+ self.running = True
+
+ if not self.ctrl:
+ self.running = False
+ cleanUp()
+ display_queue.close("rw")
+ return
+
+ # get information about the image to deduce image name and path
+ name, root, size, modificationTime = self.cardMedia.images[i]
+ image = os.path.join(root, name)
+
+ skipImage, imageMetadata, newName, newFile, path, subfolder = generateSubfolderAndFileName(
+ image, name, needMetaDataToCreateUniqueImageName,
+ needMetaDataToCreateUniqueSubfolderName)
+
+ if skipImage:
+ noImagesSkipped += 1
+ else:
+ imageDownloaded, newName, newFile = downloadImage(path, newFile, newName, name, image,
+ imageMetadata, subfolder)
+
+ if self.prefs.backup_images:
+ backupImage(subfolder, newName, imageDownloaded, newFile, image)
+
+ if imageDownloaded:
+ noImagesDownloaded += 1
+ else:
+ noImagesSkipped += 1
+ try:
+ thumbnailType, thumbnail = imageMetadata.getThumbnailData()
+ except:
+ logError(config.WARNING, _("Image has no thumbnail"), image)
+ thumbnail = orientation = None
+ else:
+ orientation = imageMetadata.orientation(missing=None)
+ display_queue.put((image_hbox.addImage, (self.thread_id, thumbnail, orientation, image, imageDownloaded)))
+
+ sizeDownloaded += size
+ percentComplete = (sizeDownloaded / sizeImages) * 100
+ if sizeDownloaded == sizeImages:
+ self.downloadComplete = True
+ progressBarText = _("%(number)s of %(total)s images copied") % {'number': i + 1, 'total': noImages}
+ display_queue.put((media_collection_treeview.updateProgress, (self.thread_id, percentComplete, progressBarText, size)))
+
+ i += 1
+
+ with self.statsLock:
+ self.downloadStats.adjust(sizeDownloaded, noImagesDownloaded, noImagesSkipped, self.noWarnings, self.noErrors)
+
+ # must manually delete these variables, or else the media cannot be unmounted (bug in pyexiv or exiv2)
+ del self.subfolderPrefsFactory, self.imageRenamePrefsFactory
+ try:
+ del imageMetadata
+ except:
+ pass
+
+ notifyAndUnmount()
+ cmd_line(_("Download complete from %s") % self.cardMedia.prettyName(limit=0))
+ display_queue.put((self.parentApp.notifyUserAllDownloadsComplete,()))
+ display_queue.put((self.parentApp.resetSequences,()))
+
+ cleanUp()
+ display_queue.put((self.parentApp.exitOnDownloadComplete, ()))
+ display_queue.close("rw")
+
+ self.running = False
+ if noImages:
+ self.lock.release()
+
+ def startStop(self):
+ if self.isAlive():
+ if self.running:
+ self.running = False
+ else:
+ try:
+ self.lock.release()
+
+ except thread_error:
+ sys.stderr.write(self.thread_id + " thread error\n")
+
+ def quit(self):
+ """
+ Quits the thread
+
+ A thread can be in one of four states:
+
+ Not started (not alive, nothing to do)
+ Started and actively running (alive)
+ Started and paused (alive)
+ Completed (not alive, nothing to do)
+ """
+
+ if self.hasStarted:
+ if self.isAlive():
+ self.ctrl = False
+
+ if not self.running:
+ released = False
+ while not released:
+ try:
+ self.lock.release()
+ released = True
+ except thread_error:
+ sys.stderr.write("Could not release lock for thread %s\n" % self.thread_id)
+
+
+
+ def on_volume_unmount(self, data1, data2):
+ """ needed for call to unmount volume"""
+ pass
+
+
+class MediaTreeView(gtk.TreeView):
+ """
+ TreeView display of memory cards and associated copying progress.
+
+ Assumes a threaded environment.
+ """
+ def __init__(self, parentApp):
+
+ self.parentApp = parentApp
+ # card name, size of images, number of images, copy progress, copy text
+ self.liststore = gtk.ListStore(str, str, int, float, str)
+ self.mapThreadToRow = {}
+
+ gtk.TreeView.__init__(self, self.liststore)
+
+ self.props.enable_search = False
+ # make it impossible to select a row
+ selection = self.get_selection()
+ selection.set_mode(gtk.SELECTION_NONE)
+
+ # Device refers to a thing like a camera, memory card in its reader, external hard drive, Portable Storage Device, etc.
+ column0 = gtk.TreeViewColumn(_("Device"), gtk.CellRendererText(),
+ text=0)
+ self.append_column(column0)
+
+ # Size refers to the total size of images on the device, typically in MB or GB
+ column1 = gtk.TreeViewColumn(_("Size"), gtk.CellRendererText(), text=1)
+ self.append_column(column1)
+
+ column2 = gtk.TreeViewColumn(_("Download Progress"),
+ gtk.CellRendererProgress(), value=3, text=4)
+ self.append_column(column2)
+ self.show_all()
+
+ def addCard(self, thread_id, cardName, sizeImages, noImages, progress = 0.0,
+ progressBarText = ''):
+ if not progressBarText:
+ progressBarText = _("0 of %s images copied") % (noImages)
+
+ # add the row, and get a temporary pointer to the row
+ iter = self.liststore.append((cardName, sizeImages, noImages,
+ progress, progressBarText))
+
+ self._setThreadMap(thread_id, iter)
+
+ # adjust scrolled window height, based on row height and number of ready to start downloads
+ if workers.noReadyToStartWorkers() >= 1 or workers.noRunningWorkers() > 0:
+ # please note, at program startup, self.rowHeight() will be less than it will be when already running
+ # e.g. when starting with 3 cards, it could be 18, but when adding 2 cards to the already running program
+ # (with one card at startup), it could be 21
+ height = (workers.noReadyToStartWorkers() + workers.noRunningWorkers() + 2) * (self.rowHeight())
+ self.parentApp.media_collection_scrolledwindow.set_size_request(-1, height)
+
+
+ def updateCard(self, thread_id, sizeImages, noImages):
+ if thread_id in self.mapThreadToRow:
+ iter = self._getThreadMap(thread_id)
+ self.liststore.set_value(iter, 1, sizeImages)
+ self.liststore.set_value(iter, 2, noImages)
+ else:
+ sys.stderr.write("FIXME: this card is unknown")
+
+ def removeCard(self, thread_id):
+ if thread_id in self.mapThreadToRow:
+ iter = self._getThreadMap(thread_id)
+ self.liststore.remove(iter)
+ del self.mapThreadToRow[thread_id]
+
+
+ def _setThreadMap(self, thread_id, iter):
+ """
+ convert the temporary iter into a tree reference, which is
+ permanent
+ """
+
+ path = self.liststore.get_path(iter)
+ treerowRef = gtk.TreeRowReference(self.liststore, path)
+ self.mapThreadToRow[thread_id] = treerowRef
+
+ def _getThreadMap(self, thread_id):
+ """
+ return the tree iter for this thread
+ """
+
+ treerowRef = self.mapThreadToRow[thread_id]
+ path = treerowRef.get_path()
+ iter = self.liststore.get_iter(path)
+ return iter
+
+ def updateProgress(self, thread_id, percentComplete, progressBarText, imageSize):
+
+ iter = self._getThreadMap(thread_id)
+
+ self.liststore.set_value(iter, 3, percentComplete)
+ self.liststore.set_value(iter, 4, progressBarText)
+ if percentComplete or imageSize:
+ self.parentApp.updateOverallProgress(thread_id, imageSize, percentComplete)
+
+
+ def rowHeight(self):
+ if not self.mapThreadToRow:
+ return 0
+ else:
+ index = self.mapThreadToRow.keys()[0]
+ path = self.mapThreadToRow[index].get_path()
+ col = self.get_column(0)
+ return self.get_background_area(path, col)[3]
+
+class ImageHBox(gtk.HBox):
+ """
+ Displays thumbnails of the images being downloaded
+ """
+
+ def __init__(self, parentApp):
+ gtk.HBox.__init__(self)
+ self.parentApp = parentApp
+ self.padding = hd.CONTROL_IN_TABLE_SPACE / 2
+
+ #create image used to lighten thumbnails
+ self.white = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, width=100, height=100)
+ #fill with white
+ self.white.fill(0xffffffff)
+
+ #load missing image
+ self.missingThumbnail = gtk.gdk.pixbuf_new_from_file_at_size(paths.share_dir('glade3/image-missing.svg'), 100, 100)
+
+ def addImage(self, thread_id, thumbnail, orientation, filename, imageDownloaded):
+ """
+ Add thumbnail
+
+ Orientation indicates if the thumbnail needs to be rotated or not.
+ """
+
+ if not thumbnail:
+ pixbuf = self.missingThumbnail
+ else:
+ try:
+ pbloader = gdk.PixbufLoader()
+ pbloader.write(thumbnail)
+ # Get the resulting pixbuf and build an image to be displayed
+ pixbuf = pbloader.get_pixbuf()
+ pbloader.close()
+
+ except:
+ log_dialog.addMessage(thread_id, config.WARNING,
+ _('Thumbnail cannot be displayed'), filename,
+ _('It may be corrupted'))
+ pixbuf = self.missingThumbnail
+
+ if not pixbuf:
+ log_dialog.addMessage(thread_id, config.WARNING,
+ _('Thumbnail cannot be displayed'), filename,
+ _('It may be corrupted'))
+ pixbuf = self.missingThumbnail
+ else:
+ # rotate if necessary
+ if orientation == 8:
+ pixbuf = pixbuf.rotate_simple(gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE)
+
+ # scale to size
+ pixbuf = common.scale2pixbuf(100, 100, pixbuf)
+ if not imageDownloaded:
+ # lighten it
+ self.white.composite(pixbuf, 0, 0, pixbuf.props.width, pixbuf.props.height, 0, 0, 1.0, 1.0, gtk.gdk.INTERP_HYPER, 180)
+
+ image = gtk.Image()
+ image.set_from_pixbuf(pixbuf)
+
+ self.pack_start(image, expand=False, padding=self.padding)
+ image.show()
+
+ # move viewport to display the latest image
+ adjustment = self.parentApp.image_scrolledwindow.get_hadjustment()
+ adjustment.set_value(adjustment.upper)
+
+
+class LogDialog(gnomeglade.Component):
+ """
+ Displays a log of errors, warnings or other information to the user
+ """
+
+ def __init__(self, parentApp):
+ """
+ Initialize values for log dialog, but do not display.
+ """
+
+ gnomeglade.Component.__init__(self,
+ paths.share_dir(config.GLADE_FILE),
+ "logdialog")
+
+
+ self.widget.connect("delete-event", self.hide_window)
+
+ self.parentApp = parentApp
+ self.log_textview.set_cursor_visible(False)
+ self.textbuffer = self.log_textview.get_buffer()
+
+ self.problemTag = self.textbuffer.create_tag(weight=pango.WEIGHT_BOLD)
+ self.resolutionTag = self.textbuffer.create_tag(style=pango.STYLE_ITALIC)
+
+ def addMessage(self, thread_id, severity, problem, details, resolution):
+ if severity in [config.CRITICAL_ERROR, config.SERIOUS_ERROR]:
+ self.parentApp.error_image.show()
+ elif severity == config.WARNING:
+ self.parentApp.warning_image.show()
+
+ iter = self.textbuffer.get_end_iter()
+ self.textbuffer.insert_with_tags(iter, problem +"\n", self.problemTag)
+ iter = self.textbuffer.get_end_iter()
+ self.textbuffer.insert(iter, details + "\n")
+ if resolution:
+ iter = self.textbuffer.get_end_iter()
+ self.textbuffer.insert_with_tags(iter, resolution +"\n", self.resolutionTag)
+
+ iter = self.textbuffer.get_end_iter()
+ self.textbuffer.insert(iter, "\n")
+
+ # move viewport to display the latest message
+ adjustment = self.log_scrolledwindow.get_vadjustment()
+ adjustment.set_value(adjustment.upper)
+
+
+ def on_logdialog_response(self, dialog, arg):
+ if arg == gtk.RESPONSE_CLOSE:
+ pass
+ self.parentApp.error_image.hide()
+ self.parentApp.warning_image.hide()
+ self.parentApp.prefs.show_log_dialog = False
+ self.widget.hide()
+ return True
+
+ def hide_window(self, window, event):
+ window.hide()
+ return True
+
+
+
+class RapidApp(gnomeglade.GnomeApp, dbus.service.Object):
+ def __init__(self, bus, path, name):
+
+ dbus.service.Object.__init__ (self, bus, path, name)
+ self.running = False
+
+ gladefile = paths.share_dir(config.GLADE_FILE)
+
+ gnomeglade.GnomeApp.__init__(self, "rapid", __version__, gladefile, "rapidapp")
+
+
+ # notifications
+ self.displayDownloadSummaryNotification = False
+ self.initPyNotify()
+
+ self.prefs = RapidPreferences()
+ self.prefs.notify_add(self.on_preference_changed)
+
+ self.testing = False
+ if self.testing:
+ self.setTestingEnv()
+
+# sys.exit(0)
+
+ self.widget.show()
+
+ displayPreferences = self.checkForUpgrade(__version__)
+ self.prefs.program_version = __version__
+
+ self.timeRemaining = TimeRemaining()
+ self._resetDownloadInfo()
+ self.statusbar_context_id = self.rapid_statusbar.get_context_id("progress")
+
+ self.error_image.hide()
+ self.warning_image.hide()
+
+ if not displayPreferences:
+ displayPreferences = not self.checkPreferencesOnStartup()
+
+ # display download information using threads
+ global media_collection_treeview, image_hbox, log_dialog
+ global download_queue, image_queue, log_queue
+ global workers
+
+ #track files that should have a suffix added to them
+ global duplicate_files
+
+ # control sequence numbers and letters
+ global sequences
+
+ duplicate_files = {}
+
+ downloadsToday = self.prefs.getAndMaybeResetDownloadsToday()
+ sequences = rn.Sequences(downloadsToday, self.prefs.stored_sequence_no)
+
+ self.downloadStats = DownloadStats()
+
+ # set the number of seconds gap with which to measure download time remaing
+ self.downloadTimeGap = 3
+
+ #locks for threadsafe file downloading and stats gathering
+ self.fileRenameLock = Lock()
+ self.fileSequenceLock = Lock()
+ self.statsLock = Lock()
+
+ # log window, in dialog format
+ # used for displaying download information to the user
+
+ log_dialog = LogDialog(self)
+
+
+ self.volumeMonitor = None
+ if self.usingVolumeMonitor():
+ self.startVolumeMonitor()
+
+
+ # set up tree view display
+ media_collection_treeview = MediaTreeView(self)
+
+ self.media_collection_vbox.pack_start(media_collection_treeview)
+
+ #thumbnail display
+ image_hbox = ImageHBox(self)
+ self.image_viewport.add(image_hbox)
+ self.image_viewport.modify_bg(gtk.STATE_NORMAL, gdk.color_parse("white"))
+ self.set_display_thumbnails(self.prefs.display_thumbnails)
+
+ self.backupVolumes = {}
+
+ self._setupDownloadbutton()
+
+ #status bar progress bar
+ self.download_progressbar = gtk.ProgressBar()
+ self.download_progressbar.set_size_request(150, -1)
+ self.download_progressbar.show()
+ self.download_progressbar_hbox.pack_start(self.download_progressbar, expand=False,
+ fill=0)
+
+
+ # menus
+# self.menu_resequence.set_sensitive(False)
+
+ self.menu_display_thumbnails.set_active(self.prefs.display_thumbnails)
+ self.menu_clear.set_sensitive(False)
+
+ self.setupAvailableImageAndBackupMedia(onStartup=True, onPreferenceChange=False, doNotAllowAutoStart = displayPreferences)
+
+ #adjust viewport size for displaying media
+ #this is important because the code in MediaTreeView.addCard() is inaccurate at program startup
+
+ height = self.media_collection_viewport.size_request()[1]
+ self.media_collection_scrolledwindow.set_size_request(-1, height)
+
+ self.download_button.grab_focus()
+
+ if displayPreferences:
+ PreferencesDialog(self)
+
+
+
+ @dbus.service.method (config.DBUS_NAME,
+ in_signature='', out_signature='b')
+ def is_running (self):
+ return self.running
+
+ @dbus.service.method (config.DBUS_NAME,
+ in_signature='', out_signature='')
+ def start (self):
+ if self.is_running():
+ self.rapidapp.present()
+ else:
+ self.running = True
+ self.main()
+ self.running = False
+
+ def setTestingEnv(self):
+ self.prefs.program_version = '0.0.8~b7'
+ r = ['Date time', 'Image date', 'YYYYMMDD', 'Text', '-', '', 'Date time', 'Image date', 'HHMM', 'Text', '-', '', 'Session number', '1', 'Three digits', 'Text', '-iso', '', 'Metadata', 'ISO', '', 'Text', '-f', '', 'Metadata', 'Aperture', '', 'Text', '-', '', 'Metadata', 'Focal length', '', 'Text', 'mm-', '', 'Metadata', 'Exposure time', '', 'Filename', 'Extension', 'lowercase']
+ self.prefs.image_rename = r
+
+
+
+ def checkPreferencesOnStartup(self):
+ prefsOk = rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder)
+ if not prefsOk:
+ title = PROGRAM_NAME
+ msg = _("There is an error in the program preferences.")
+ msg += " " + _("Some preferences will be reset.")
+ sys.stderr.write(msg +'\n')
+# misc.run_dialog(title, msg)
+ return prefsOk
+
+ def checkForUpgrade(self, runningVersion):
+ """ Checks if the running version of the program is different from the version recorded in the preferences.
+
+ If the version is different, then the preferences are checked to see whether they should be upgraded or not.
+
+ returns True if program preferences window should be opened """
+
+ displayPrefs = upgraded = False
+
+ previousVersion = self.prefs.program_version
+ if previousVersion:
+ # the program has been run previously for this user
+
+ pv = common.pythonifyVersion(previousVersion)
+ rv = common.pythonifyVersion(runningVersion)
+
+ title = PROGRAM_NAME
+ imageRename = subfolder = None
+
+ if pv != rv:
+ if pv > rv:
+ prefsOk = rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder)
+
+ msg = _("A newer version of this program was previously run on this computer.\n\n")
+ if prefsOk:
+ msg += _("Program preferences appear to be valid, but please check them to ensure correct operation.")
+ else:
+ msg += _("Sorry, some preferences are invalid and will be reset.")
+ sys.stderr.write(_("Warning:") + " %s\n" % msg)
+ misc.run_dialog(title, msg)
+ displayPrefs = True
+
+ else:
+ cmd_line(_("This version of the program is newer than the previously run version. Checking preferences."))
+# if True:
+ if rn.checkPreferencesForValidity(self.prefs.image_rename, self.prefs.subfolder, previousVersion):
+ upgraded, imageRename, subfolder = rn.upgradePreferencesToCurrent(self.prefs.image_rename, self.prefs.subfolder, previousVersion)
+ if upgraded:
+ self.prefs.image_rename = imageRename
+ self.prefs.subfolder = subfolder
+ cmd_line(_("Preferences were modified."))
+ msg = _('This version of the program uses different preferences than the old version. Your preferences have been updated.\n\nPlease check them to ensure correct operation.')
+ misc.run_dialog(title, msg)
+ displayPrefs = True
+ else:
+ cmd_line(_("No preferences needed to be changed."))
+ else:
+ msg = _('This version of the program uses different preferences than the old version. Some of your previous preferences were invalid, and could not be updated. They will be reset.')
+ sys.stderr.write(msg + "\n")
+ misc.run_dialog(title, msg)
+ displayPrefs = True
+
+ return displayPrefs
+
+ def initPyNotify(self):
+ if not pynotify.init("TestCaps"):
+ sys.stderr.write(_("Problem using pynotify.") + "\n")
+ sys.exit(1)
+
+ capabilities = {'actions': False,
+ 'body': False,
+ 'body-hyperlinks': False,
+ 'body-images': False,
+ 'body-markup': False,
+ 'icon-multi': False,
+ 'icon-static': False,
+ 'sound': False,
+ 'image/svg+xml': False,
+ 'append': False}
+
+ caps = pynotify.get_server_caps ()
+ if caps is None:
+ sys.stderr.write(_("Failed to receive pynotify server capabilities.") + "\n")
+ sys.exit (1)
+
+ for cap in caps:
+ capabilities[cap] = True
+
+ info = pynotify.get_server_info()
+
+ def usingVolumeMonitor(self):
+ """
+ Returns True if programs needs to use gnomevfs volume monitor
+ """
+
+ return (self.prefs.device_autodetection or
+ (self.prefs.backup_images and
+ self.prefs.backup_device_autodetection
+ ))
+
+
+ def startVolumeMonitor(self):
+ if not self.volumeMonitor:
+ self.volumeMonitor = VMonitor(self)
+
+ def displayBackupVolumes(self):
+ """
+ Create a message to be displayed to the user showing which backup volumes will be used
+ """
+ message = ''
+
+ paths = self.backupVolumes.keys()
+ i = 0
+ v = len(paths)
+ prefix = ''
+ for b in paths:
+ if v > 1:
+ if i < (v -1) and i > 0:
+ prefix = ', '
+ elif i == (v - 1) :
+ prefix = " " + _("and") + " "
+ i += 1
+ message = "%s%s'%s'" % (message, prefix, self.backupVolumes[b].get_name())
+
+ if v > 1:
+ message = _("Using backup devices") + " %s" % message
+ elif v == 1:
+ message = _("Using backup device") + " %s" % message
+ else:
+ message = _("No backup devices detected")
+
+ return message
+
+ def searchForPsd(self):
+ """
+ Check to see if user preferences are to automatically search for Portable Storage Devices or not
+ """
+ return self.prefs.device_autodetection_psd and self.prefs.device_autodetection
+
+
+ def isGProxyShadowMount(self, gvfsVolume):
+
+ """ gvfs GProxyShadowMount are used for camera specific things, not the data in the memory card """
+ if using_gio:
+ #FIXME: this is a hack, but what is the correct function?
+ return str(type(gvfsVolume)).find('GProxyShadowMount') >= 0
+ else:
+ return False
+
+ def workerHasThisPath(self, path):
+ havePath= False
+ for w in workers.getNonFinishedWorkers():
+ if w.cardMedia.path == path:
+ havePath = True
+ break
+ return havePath
+
+ def on_volume_mounted(self, monitor, mount):
+ """
+ callback run when gnomevfs indicates a new volume
+ has been mounted
+ """
+
+ if self.usingVolumeMonitor():
+ volume = Volume(mount)
+ path = volume.get_path()
+ if not self.isGProxyShadowMount(mount):
+ self._printDetectedDevice(volume.get_name(limit=0), path)
+
+ isBackupVolume = self.checkIfBackupVolume(path)
+
+ if isBackupVolume:
+ backupPath = os.path.join(path, self.prefs.backup_identifier)
+ if path not in self.backupVolumes:
+ self.backupVolumes[backupPath] = volume
+ self.rapid_statusbar.push(self.statusbar_context_id, self.displayBackupVolumes())
+
+ elif media.isImageMedia(path) or self.searchForPsd():
+ cardMedia = CardMedia(path, volume, True)
+ i = workers.getNextThread_id()
+
+ self._printAutoStart(self.prefs.auto_download_upon_device_insertion)
+
+ workers.append(CopyPhotos(i, self, self.fileRenameLock, self.fileSequenceLock, self.statsLock,
+ self.downloadStats, self.prefs.auto_download_upon_device_insertion,
+ cardMedia))
+
+
+ self.setDownloadButtonSensitivity()
+ self.startScan()
+
+
+ def on_volume_unmounted(self, monitor, volume):
+ """
+ callback run when gnomevfs indicates a volume
+ has been unmounted
+ """
+ volume = Volume(volume)
+ path = volume.get_path()
+
+ # four scenarios -
+ # volume is waiting to be scanned
+ # the volume has been scanned but downloading has not yet started
+ # images are being downloaded from volume (it must be a messy unmount)
+ # images finished downloading from volume
+
+ if path:
+ # first scenario
+ for w in workers.getReadyToStartWorkers():
+ if w.cardMedia.volume == volume:
+ media_collection_treeview.removeCard(w.thread_id)
+ workers.disableWorker(w.thread_id)
+ # second scenario
+ for w in workers.getReadyToDownloadWorkers():
+ if w.cardMedia.volume == volume:
+ media_collection_treeview.removeCard(w.thread_id)
+ workers.disableWorker(w.thread_id)
+
+ # fourth scenario - nothing to do
+
+ # remove backup volumes
+ backupPath = os.path.join(path, self.prefs.backup_identifier)
+ if backupPath in self.backupVolumes:
+ del self.backupVolumes[backupPath]
+ self.rapid_statusbar.push(self.statusbar_context_id, self.displayBackupVolumes())
+
+
+
+ def clearCompletedDownloads(self):
+ """
+ clears the display of completed downloads
+ """
+
+ for w in workers.getFinishedWorkers():
+ media_collection_treeview.removeCard(w.thread_id)
+
+
+
+
+ def clearNotStartedDownloads(self):
+ """
+ Clears the display of the download and instructs the thread not to run
+ """
+
+ for w in workers.getNotDownloadingWorkers():
+ media_collection_treeview.removeCard(w.thread_id)
+ workers.disableWorker(w.thread_id)
+
+ def checkIfBackupVolume(self, path):
+ """
+ Checks to see if backups are enabled and path represents a valid backup location
+
+ Checks against user preferences.
+ """
+ if self.prefs.backup_images:
+ if self.prefs.backup_device_autodetection:
+ if media.isBackupMedia(path, self.prefs.backup_identifier):
+ return True
+ elif path == self.prefs.backup_location:
+ # user manually specified the path
+ return True
+ return False
+
+ def _printDetectedDevice(self, volume_name, path):
+ cmd_line (_("Detected %(device)s with path %(path)s") % {'device': volume_name, 'path': path})
+
+ def _printAutoStart(self, autoStart):
+ if autoStart:
+ cmd_line(_("Automatically start download is true") )
+ else:
+ cmd_line(_("Automatically start download is false") )
+
+ def setupAvailableImageAndBackupMedia(self, onStartup, onPreferenceChange, doNotAllowAutoStart):
+ """
+ Creates a list of CardMedia
+
+ onStartup should be True if the program is still starting, i.e. this is being called from the
+ program's initialization.
+
+ onPreferenceChange should be True if this is being called as the result of a preference
+ bring changed
+
+ Removes any image media that are currently not downloaded,
+ or finished downloading
+ """
+
+ self.clearNotStartedDownloads()
+
+ cardMediaList = []
+ self.backupVolumes = {}
+
+ if not workers.noDownloadingWorkers():
+ self.downloadStats.clear()
+ self._resetDownloadInfo()
+
+ if self.usingVolumeMonitor():
+ # either using automatically detected backup devices
+ # or image devices
+
+ for v in self.volumeMonitor.get_mounts():
+ volume = Volume(v)
+ path = volume.get_path(avoid_gnomeVFS_bug = True)
+
+ if path:
+ if not self.isGProxyShadowMount(v):
+ self._printDetectedDevice(volume.get_name(limit=0), path)
+ isBackupVolume = self.checkIfBackupVolume(path)
+ if isBackupVolume:
+ backupPath = os.path.join(path, self.prefs.backup_identifier)
+ self.backupVolumes[backupPath] = volume
+ elif self.prefs.device_autodetection and (media.isImageMedia(path) or self.searchForPsd()):
+ cardMediaList.append(CardMedia(path, volume, True))
+
+
+ if not self.prefs.device_autodetection:
+ # user manually specified the path from which to download images
+ path = self.prefs.device_location
+ if path:
+ cmd_line(_("Using manually specified path") + " %s" % path)
+ cardMedia = CardMedia(path, None, True)
+ cardMediaList.append(cardMedia)
+
+ if self.prefs.backup_images:
+ if not self.prefs.backup_device_autodetection:
+ # user manually specified backup location
+ self.backupVolumes[self.prefs.backup_location] = None
+ self.rapid_statusbar.push(self.statusbar_context_id, '')
+ else:
+ self.rapid_statusbar.push(self.statusbar_context_id, self.displayBackupVolumes())
+
+ else:
+ self.rapid_statusbar.push(self.statusbar_context_id, '')
+
+ # add each memory card / other device to the list of threads
+ j = workers.getNextThread_id()
+
+ if doNotAllowAutoStart:
+ autoStart = False
+ else:
+ autoStart = (not onPreferenceChange) and ((self.prefs.auto_download_at_startup and onStartup) or (self.prefs.auto_download_upon_device_insertion and not onStartup))
+
+ self._printAutoStart(autoStart)
+
+ for i in range(j, j + len(cardMediaList)):
+ cardMedia = cardMediaList[i - j]
+ workers.append(CopyPhotos(i, self, self.fileRenameLock, self.fileSequenceLock, self.statsLock,
+ self.downloadStats, autoStart, cardMedia))
+
+
+ self.setDownloadButtonSensitivity()
+ self.startScan()
+
+ def _setupDownloadbutton(self):
+
+ self.download_hbutton_box = gtk.HButtonBox()
+ self.download_button_is_download = True
+ self.download_button = gtk.Button()
+ self.download_button.set_use_underline(True)
+ self._set_download_button()
+ self.download_button.connect('clicked', self.on_download_button_clicked)
+ self.download_hbutton_box.set_layout(gtk.BUTTONBOX_START)
+ self.download_hbutton_box.pack_start(self.download_button)
+ self.download_hbutton_box.show_all()
+ self.buttons_hbox.pack_start(self.download_hbutton_box,
+ padding=hd.WINDOW_BORDER_SPACE)
+
+ self.setDownloadButtonSensitivity()
+
+
+ def set_display_thumbnails(self, value):
+ if value:
+ self.image_scrolledwindow.show_all()
+ else:
+ self.image_scrolledwindow.hide()
+
+
+ def _resetDownloadInfo(self):
+ self.markSet = False
+ self.startTime = None
+ self.totalDownloadSize = self.totalDownloadedSoFar = 0
+ self.totalDownloadSizeThisRun = self.totalDownloadedSoFarThisRun = 0
+ self.timeRemaining.clear()
+
+ def addToTotalDownloadSize(self, size):
+ self.totalDownloadSize += size
+
+ def setOverallDownloadMark(self):
+ if not self.markSet:
+ self.markSet = True
+ self.totalDownloadSizeThisRun = self.totalDownloadSize - self.totalDownloadedSoFar
+ self.totalDownloadedSoFarThisRun = 0
+
+ self.startTime = time.time()
+ self.timeStatusBarUpdated = self.startTime
+
+ self.timeMark = self.startTime
+ self.sizeMark = 0
+
+ def startOrResumeWorkers(self):
+
+ # resume any paused workers
+ for w in workers.getPausedDownloadingWorkers():
+ w.startStop()
+ self.timeRemaining.setTimeMark(w)
+
+ #start any new workers
+ workers.startDownloadingWorkers()
+
+ if is_beta and verbose:
+ workers.printWorkerStatus()
+
+
+ def updateOverallProgress(self, thread_id, imageSize, percentComplete):
+ """
+ Updates progress bar and status bar text with time remaining
+ to download images
+ """
+
+ self.totalDownloadedSoFar += imageSize
+ self.totalDownloadedSoFarThisRun += imageSize
+
+ fraction = self.totalDownloadedSoFar / float(self.totalDownloadSize)
+
+ self.download_progressbar.set_fraction(fraction)
+
+ if percentComplete == 100.0:
+ self.menu_clear.set_sensitive(True)
+ self.timeRemaining.remove(thread_id)
+
+ if self.downloadComplete():
+ # finished all downloads
+ self.rapid_statusbar.push(self.statusbar_context_id, "")
+ self.download_button_is_download = True
+ self._set_download_button()
+ self.setDownloadButtonSensitivity()
+ cmd_line(_("All downloads complete"))
+ if is_beta and verbose:
+ workers.printWorkerStatus()
+
+ else:
+ now = time.time()
+ self.timeRemaining.update(thread_id, imageSize)
+
+ if now > (self.downloadTimeGap + self.timeMark):
+ amtTime = now - self.timeMark
+ self.timeMark = now
+ amtDownloaded = self.totalDownloadedSoFarThisRun - self.sizeMark
+ self.sizeMark = self.totalDownloadedSoFarThisRun
+ amtToDownload = float(self.totalDownloadSizeThisRun) - self.totalDownloadedSoFarThisRun
+ downloadSpeed = "%1.1f" % (amtDownloaded / 1048576 / amtTime) +_("MB/s")
+ self.speed_label.set_text(downloadSpeed)
+
+ timeRemaining = self.timeRemaining.timeRemaining()
+ if timeRemaining:
+ secs = int(timeRemaining)
+
+ if secs == 0:
+ message = ""
+ elif secs == 1:
+ message = _("About 1 second remaining")
+ elif secs < 60:
+ message = _("About %i seconds remaining") % secs
+ elif secs == 60:
+ message = _("About 1 minute remaining")
+ else:
+ # Translators: in the text '%(minutes)i:%(seconds)02i', only the : should be translated, if needed.
+ # '%(minutes)i' and '%(seconds)02i' should not be modified or left out. They are used to format and display the amount
+ # of time the download has remainging, e.g. 'About 5:36 minutes remaining'
+ message = _("About %(minutes)i:%(seconds)02i minutes remaining") % {'minutes': secs / 60, 'seconds': secs % 60}
+
+ self.rapid_statusbar.push(self.statusbar_context_id, message)
+
+
+ def resetSequences(self):
+ if self.downloadComplete():
+ sequences.reset(self.prefs.getDownloadsToday(), self.prefs.stored_sequence_no)
+
+ def notifyUserAllDownloadsComplete(self):
+ """ Possibly notify the user all downloads are complete using libnotify
+
+ Reset progress bar info"""
+
+ if self.downloadComplete():
+ if self.displayDownloadSummaryNotification:
+ message = _("All downloads complete")
+ message += "\n%s " % self.downloadStats.noImagesDownloaded + _("images downloaded")
+ if self.downloadStats.noImagesSkipped:
+ message = "%s\n%s " % (message, self.downloadStats.noImagesSkipped) + _("images skipped")
+ if self.downloadStats.noWarnings:
+ message = "%s\n%s " % (message, self.downloadStats.noWarnings) + _("warnings")
+ if self.downloadStats.noErrors:
+ message = "%s\n%s " % (message, self.downloadStats.noErrors) +_("errors")
+ n = pynotify.Notification(PROGRAM_NAME, message)
+ n.show()
+ self.displayDownloadSummaryNotification = False # don't show it again unless needed
+ self.downloadStats.clear()
+ self._resetDownloadInfo()
+ self.speed_label.set_text(' ')
+
+ def exitOnDownloadComplete(self):
+ if self.downloadComplete():
+ if self.prefs.auto_exit:
+ if not (self.downloadStats.noErrors or self.downloadStats.noWarnings):
+ self.quit()
+
+ def downloadComplete(self):
+ return self.totalDownloadedSoFar == self.totalDownloadSize
+
+ def setDownloadButtonSensitivity(self):
+
+ isSensitive = workers.noReadyToDownloadWorkers() > 0 or workers.noDownloadingWorkers() > 0
+
+ if isSensitive:
+ self.download_button.props.sensitive = True
+ self.menu_download_pause.props.sensitive = True
+ else:
+ self.download_button.props.sensitive = False
+ self.menu_download_pause.props.sensitive = False
+
+ return isSensitive
+
+
+ def on_rapidapp_destroy(self, widget):
+ """Called when the application is going to quit"""
+ workers.quitAllWorkers()
+
+ self.flushevents()
+
+ display_queue.close("w")
+
+
+ def on_menu_clear_activate(self, widget):
+ self.clearCompletedDownloads()
+ widget.set_sensitive(False)
+
+ def on_menu_report_problem_activate(self, widget):
+ webbrowser.open("https://bugs.launchpad.net/rapid")
+
+ def on_menu_get_help_online_activate(self, widget):
+ webbrowser.open("http://www.damonlynch.net/rapid/help.html")
+
+ def on_menu_donate_activate(self, widget):
+ webbrowser.open("http://www.damonlynch.net/rapid/donate.html")
+
+ def on_menu_translate_activate(self, widget):
+ webbrowser.open("http://www.damonlynch.net/rapid/translate.html")
+
+ def on_menu_preferences_activate(self, widget):
+ """ Sets preferences for the application using dialog window """
+
+ PreferencesDialog(self)
+
+ def on_menu_log_window_toggled(self, widget):
+ active = widget.get_active()
+ self.prefs.show_log_dialog = active
+ if active:
+ log_dialog.widget.show()
+ else:
+ log_dialog.widget.hide()
+
+ def on_menu_display_thumbnails_toggled(self, check_button):
+ self.prefs.display_thumbnails = check_button.get_active()
+
+ def on_menu_about_activate(self, widget):
+ """ Display about dialog box """
+
+ about = gtk.glade.XML(paths.share_dir(config.GLADE_FILE), "about").get_widget("about")
+ about.set_property("name", PROGRAM_NAME)
+ about.set_property("version", __version__)
+ about.run()
+ about.destroy()
+
+ def _set_download_button(self):
+ """
+ Sets download button to appropriate state
+ """
+ if self.download_button_is_download:
+ # This text will be displayed to the user on the Download / Pause button.
+ # Please note the space at the end of the label - it is needed to meet the Gnome Human Interface Guidelines
+ self.download_button.set_label(_("_Download "))
+ self.download_button.set_image(gtk.image_new_from_stock(
+ gtk.STOCK_CONVERT,
+ gtk.ICON_SIZE_BUTTON))
+ else:
+ # button should indicate paused state
+ self.download_button.set_image(gtk.image_new_from_stock(
+ gtk.STOCK_MEDIA_PAUSE,
+ gtk.ICON_SIZE_BUTTON))
+ # This text will be displayed to the user on the Download / Pause button.
+ self.download_button.set_label(_("_Pause") + " ")
+
+ def on_menu_download_pause_activate(self, widget):
+ self.on_download_button_clicked(widget)
+
+ def startScan(self):
+ if workers.noReadyToStartWorkers() > 0:
+ workers.startWorkers()
+
+
+
+ def postStartDownloadTasks(self):
+ if workers.noDownloadingWorkers() > 1:
+ self.displayDownloadSummaryNotification = True
+
+ # set button to display Pause
+ self.download_button_is_download = False
+ self._set_download_button()
+
+ def startDownload(self):
+ self.startOrResumeWorkers()
+ self.postStartDownloadTasks()
+
+ def pauseDownload(self):
+ for w in workers.getDownloadingWorkers():
+ w.startStop()
+ # set button to display Download
+ if not self.download_button_is_download:
+ self.download_button_is_download = True
+ self._set_download_button()
+
+ def on_download_button_clicked(self, widget):
+ """
+ Handle download button click.
+
+ Button is in one of two states: download, or pause.
+
+ If download, a click indicates to start or resume a download run.
+ If pause, a click indicates to pause all running downloads.
+ """
+ if self.download_button_is_download:
+ self.startDownload()
+ else:
+ self.pauseDownload()
+
+ def on_preference_changed(self, key, value):
+
+ if key == 'display_thumbnails':
+ self.set_display_thumbnails(value)
+ elif key == 'show_log_dialog':
+ self.menu_log_window.set_active(value)
+ elif key in ['device_autodetection', 'device_autodetection_psd', 'backup_images', 'device_location',
+ 'backup_device_autodetection', 'backup_location' ]:
+ if self.usingVolumeMonitor():
+ self.startVolumeMonitor()
+ cmd_line("\n" + _("Preferences were changed."))
+ self.setupAvailableImageAndBackupMedia(onStartup = False, onPreferenceChange = True, doNotAllowAutoStart = False)
+ if is_beta and verbose:
+ print "Current worker status:"
+ workers.printWorkerStatus()
+
+ def on_error_eventbox_button_press_event(self, widget, event):
+ self.prefs.show_log_dialog = True
+ log_dialog.widget.show()
+
+class VMonitor:
+ """ Transistion to gvfs from gnomevfs"""
+ def __init__(self, app):
+ self.app = app
+ if using_gio:
+ self.vmonitor = gio.volume_monitor_get()
+ self.vmonitor.connect("mount-added", self.app.on_volume_mounted)
+ self.vmonitor.connect("mount-removed", self.app.on_volume_unmounted)
+ else:
+ self.vmonitor = gnomevfs.VolumeMonitor()
+ self.vmonitor.connect("volume-mounted", self.app.on_volume_mounted)
+ self.vmonitor.connect("volume-unmounted", self.app.on_volume_unmounted)
+
+
+ def get_mounts(self):
+ if using_gio:
+ return self.vmonitor.get_mounts()
+ else:
+ return self.vmonitor.get_mounted_volumes()
+
+class Volume:
+ """ Transistion to gvfs from gnomevfs"""
+ def __init__(self, volume):
+ self.volume = volume
+
+ def get_name(self, limit=config.MAX_LENGTH_DEVICE_NAME):
+ if using_gio:
+ v = self.volume.get_name()
+ else:
+ v = self.volume.get_display_name()
+
+ if limit:
+ if len(v) > limit:
+ v = v[:limit] + '...'
+ return v
+
+ def get_path(self, avoid_gnomeVFS_bug = False):
+ if using_gio:
+ path = self.volume.get_root().get_path()
+ else:
+ uri = self.volume.get_activation_uri()
+ path = None
+ if avoid_gnomeVFS_bug:
+ # ugly hack to work around bug where gnomevfs.get_local_path_from_uri(uri) causes a crash
+ mediaLocation = "file://" + config.MEDIA_LOCATION
+ if uri.find(mediaLocation) == 0:
+ path = gnomevfs.get_local_path_from_uri(uri)
+ else:
+ path = gnomevfs.get_local_path_from_uri(uri)
+ return path
+
+ def unmount(self, callback):
+ self.volume.unmount(callback)
+
+class DownloadStats:
+ def __init__(self):
+ self.clear()
+
+ def adjust(self, size, noImagesDownloaded, noImagesSkipped, noWarnings, noErrors):
+ self.downloadSize += size
+ self.noImagesDownloaded += noImagesDownloaded
+ self.noImagesSkipped += noImagesSkipped
+ self.noWarnings += noWarnings
+ self.noErrors += noErrors
+
+ def clear(self):
+ self.noImagesDownloaded = self.noImagesSkipped = 0
+ self.downloadSize = 0
+ self.noWarnings = self.noErrors = 0
+
+class TimeForDownload:
+ pass
+
+class TimeRemaining:
+ gap = 2
+ def __init__(self):
+ self.clear()
+
+ def add(self, w, size):
+ if w not in self.times:
+ t = TimeForDownload()
+ t.timeRemaining = None
+ t.size = size
+ t.downloaded = 0
+ t.sizeMark = 0
+ t.timeMark = time.time()
+ self.times[w] = t
+
+ def update(self, w, size):
+ if w in self.times:
+ self.times[w].downloaded += size
+ now = time.time()
+ tm = self.times[w].timeMark
+ amtTime = now - tm
+ if amtTime > self.gap:
+ self.times[w].timeMark = now
+ amtDownloaded = self.times[w].downloaded - self.times[w].sizeMark
+ self.times[w].sizeMark = self.times[w].downloaded
+ timefraction = amtDownloaded / amtTime
+ amtToDownload = float(self.times[w].size) - self.times[w].downloaded
+ self.times[w].timeRemaining = amtToDownload / timefraction
+
+ def _timeEstimates(self):
+ for t in self.times:
+ yield self.times[t].timeRemaining
+
+ def timeRemaining(self):
+ return max(self._timeEstimates())
+
+ def setTimeMark(self, w):
+ if w in self.times:
+ self.times[w].timeMark = time.time()
+
+ def clear(self):
+ self.times = {}
+
+ def remove(self, w):
+ if w in self.times:
+ del self.times[w]
+
+def programStatus():
+ print _("Goodbye")
+
+
+def start ():
+ global is_beta
+ is_beta = config.version.find('~b') > 0
+
+ parser = OptionParser(version= "%%prog %s" % config.version)
+ parser.set_defaults(verbose=is_beta, extensions=False)
+ # Translators: this text is displayed to the user when they request information on the command line options.
+ # The text %default should not be modified or left out.
+ parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help=_("display program information on the command line as the program runs (default: %default)"))
+ parser.add_option("-q", "--quiet", action="store_false", dest="verbose", help=_("only output errors to the command line"))
+ # image file extensions are recognized RAW files plus TIFF and JPG
+ parser.add_option("-e", "--extensions", action="store_true", dest="extensions", help=_("list image file extensions the program recognizes and exit"))
+ (options, args) = parser.parse_args()
+ global verbose
+ verbose = options.verbose
+
+ if verbose:
+ atexit.register(programStatus)
+
+ if options.extensions:
+ exts = config.RAW_FILE_EXTENSIONS + config.NON_RAW_IMAGE_FILE_EXTENSIONS
+ v = ''
+ for e in exts[:-1]:
+ v += '%s, ' % e.upper()
+ v = v[:-1] + ' '+ (_('and %s') % exts[-1].upper())
+ print v
+ sys.exit(0)
+
+ if using_gio:
+ cmd_line(_("Using") + " GIO")
+ else:
+ # Which volume management code is being used (GIO or GnomeVFS)
+ cmd_line(_("Using") + " GnomeVFS")
+
+ gdk.threads_init()
+ display_queue.open("rw")
+ tube.tube_add_watch(display_queue, updateDisplay)
+ gdk.threads_enter()
+
+ # run only a single instance of the application
+ bus = dbus.SessionBus ()
+ request = bus.request_name (config.DBUS_NAME, dbus.bus.NAME_FLAG_DO_NOT_QUEUE)
+ if request != dbus.bus.REQUEST_NAME_REPLY_EXISTS:
+ app = RapidApp (bus, '/', config.DBUS_NAME)
+ else:
+ # this application is already running
+ print _("%s is already running") % PROGRAM_NAME
+ object = bus.get_object (config.DBUS_NAME, "/")
+ app = dbus.Interface (object, config.DBUS_NAME)
+
+ app.start()
+ gdk.threads_leave()
+
+if __name__ == "__main__":
+ start()
diff --git a/rapid/renamesubfolderprefs.py b/rapid/renamesubfolderprefs.py
new file mode 100644
index 0000000..9804c59
--- /dev/null
+++ b/rapid/renamesubfolderprefs.py
@@ -0,0 +1,1470 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+""" Define and test preferences for use in PlusMinus tables.
+
+These are displayed to the user as a series of rows in the user
+preferences dialog window.
+
+Preferences for subfolders and image renaming are defined below
+in dictionaries and lists. This makes it easier for checking validity and
+creating combo boxes.
+
+There are 3 levels: 0, 1 and 2, which specify the depth of the pref value.
+Level 0 is the topmost level, and corresponds to the first entry in the
+row of preferences the user sees in the preferences dialog window.
+
+Custom exceptions are defined to handle invalid preferences.
+
+The user's actual preferences, on the other hand, are stored in flat lists.
+Each list has members which are a multiple of 3 in length.
+Each group of 3 members is equal to one line of preferences in the plus minus
+table.
+"""
+#needed for python 2.5, unneeded for python 2.6
+from __future__ import with_statement
+
+import string
+
+import os
+import re
+import sys
+
+import gtk.gdk as gdk
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+except:
+ pass
+try:
+ import gtk
+except:
+ sys.exit(1)
+
+from common import Configi18n
+global _
+_ = Configi18n._
+
+import datetime
+
+import ValidatedEntry
+import config
+
+from common import pythonifyVersion
+
+# Special key in each dictionary which specifies the order of elements.
+# It is very important to have a consistent and rational order when displaying
+# these prefs to the user, and dictionaries are unsorted.
+
+ORDER_KEY = "__order__"
+
+# PLEASE NOTE: these values are duplicated in a dummy class whose function
+# is to have them put into the translation template. If you change the values below
+# then change the value in class i18TranslateMeThanks as well!! Thanks!!
+
+# *** Level 0
+DATE_TIME = 'Date time'
+TEXT = 'Text'
+FILENAME = 'Filename'
+METADATA = 'Metadata'
+SEQUENCES = 'Sequences'
+
+SEPARATOR = os.sep
+
+# *** Level 1
+
+# Date time
+IMAGE_DATE = 'Image date'
+TODAY = 'Today'
+YESTERDAY = 'Yesterday'
+
+# File name
+NAME_EXTENSION = 'Name + extension'
+NAME = 'Name'
+EXTENSION = 'Extension'
+IMAGE_NUMBER = 'Image number'
+
+# Metadata
+APERTURE = 'Aperture'
+ISO = 'ISO'
+EXPOSURE_TIME = 'Exposure time'
+FOCAL_LENGTH = 'Focal length'
+CAMERA_MAKE = 'Camera make'
+CAMERA_MODEL = 'Camera model'
+SHORT_CAMERA_MODEL = 'Short camera model'
+SHORT_CAMERA_MODEL_HYPHEN = 'Hyphenated short camera model'
+SERIAL_NUMBER = 'Serial number'
+SHUTTER_COUNT = 'Shutter count'
+OWNER_NAME = 'Owner name'
+
+#Image sequences
+DOWNLOAD_SEQ_NUMBER = 'Downloads today'
+SESSION_SEQ_NUMBER = 'Session number'
+SUBFOLDER_SEQ_NUMBER = 'Subfolder number'
+STORED_SEQ_NUMBER = 'Stored number'
+
+SEQUENCE_LETTER = 'Sequence letter'
+
+
+
+# *** Level 2
+
+# Image number
+IMAGE_NUMBER_ALL = 'All digits'
+IMAGE_NUMBER_1 = 'Last digit'
+IMAGE_NUMBER_2 = 'Last 2 digits'
+IMAGE_NUMBER_3 = 'Last 3 digits'
+IMAGE_NUMBER_4 = 'Last 4 digits'
+
+
+# Case
+ORIGINAL_CASE = "Original Case"
+UPPERCASE = "UPPERCASE"
+LOWERCASE = "lowercase"
+
+# Sequence number
+SEQUENCE_NUMBER_1 = "One digit"
+SEQUENCE_NUMBER_2 = "Two digits"
+SEQUENCE_NUMBER_3 = "Three digits"
+SEQUENCE_NUMBER_4 = "Four digits"
+SEQUENCE_NUMBER_5 = "Five digits"
+SEQUENCE_NUMBER_6 = "Six digits"
+
+
+# Now, define dictionaries and lists of valid combinations of preferences.
+
+# Level 2
+
+# Date
+
+SUBSECONDS = 'Subseconds'
+
+# ****** note if changing LIST_DATE_TIME_L2, update the default subfolder preference below :D *****
+LIST_DATE_TIME_L2 = ['YYYYMMDD', 'YYYY-MM-DD','YYMMDD', 'YY-MM-DD',
+ 'MMDDYYYY', 'MMDDYY', 'MMDD',
+ 'DDMMYYYY', 'DDMMYY', 'YYYY', 'YY',
+ 'MM', 'DD',
+ 'HHMMSS', 'HHMM']
+
+LIST_IMAGE_DATE_TIME_L2 = LIST_DATE_TIME_L2 + [SUBSECONDS]
+
+DEFAULT_SUBFOLDER_PREFS = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[9], '/', '', '', DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]]
+
+class i18TranslateMeThanks:
+ """ this class is never used in actual running code
+ It's purpose is to have these values inserted into the program's i18n template file
+
+ """
+ def __init__(self):
+ _('Date time')
+ _('Text')
+ _('Filename')
+ _('Metadata')
+ _('Sequences')
+ _('Image date')
+ _('Today')
+ _('Yesterday')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Name + extension')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Name')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Extension')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Image number')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Aperture')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('ISO')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Exposure time')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Focal length')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Camera make')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Camera model')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Short camera model')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Hyphenated short camera model')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Serial number')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Shutter count')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamemetadata
+ _('Owner name')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+ _('Downloads today')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+ _('Session number')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+ _('Subfolder number')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequencenumbers
+ _('Stored number')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#sequenceletters
+ _('Sequence letter')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('All digits')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Last digit')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Last 2 digits')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Last 3 digits')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamefilename
+ _('Last 4 digits')
+ # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+ _("Original Case")
+ # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+ _("UPPERCASE")
+ # Translators: please not the capitalization of this text, and keep it the same if your language features capitalization
+ _("lowercase")
+ _("One digit")
+ _("Two digits")
+ _("Three digits")
+ _("Four digits")
+ _("Five digits")
+ _("Six digits")
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('Subseconds')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('YYYYMMDD')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('YYYY-MM-DD')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('YYMMDD')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('YY-MM-DD')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('MMDDYYYY')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('MMDDYY')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('MMDD')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('DDMMYYYY')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('DDMMYY')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('YYYY')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('YY')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('MM')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('DD')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('HHMMSS')
+ # Translators: for an explanation of what this means, see http://damonlynch.net/rapid/documentation/index.html#renamedateandtime
+ _('HHMM')
+
+
+# Convenience values for python datetime conversion using values in
+# LIST_DATE_TIME_L2. Obviously the two must remain synchronized.
+
+DATE_TIME_CONVERT = ['%Y%m%d', '%Y-%m-%d','%y%m%d', '%y-%m-%d',
+ '%m%d%Y', '%m%d%y', '%m%d',
+ '%d%m%Y', '%d%m%y', '%Y', '%y',
+ '%m', '%d',
+ '%H%M%S', '%H%M']
+
+
+LIST_IMAGE_NUMBER_L2 = [IMAGE_NUMBER_ALL, IMAGE_NUMBER_1, IMAGE_NUMBER_2,
+ IMAGE_NUMBER_3, IMAGE_NUMBER_4]
+
+
+LIST_CASE_L2 = [ORIGINAL_CASE, UPPERCASE, LOWERCASE]
+
+LIST_SEQUENCE_LETTER_L2 = [
+ UPPERCASE,
+ LOWERCASE
+ ]
+
+
+
+LIST_SEQUENCE_NUMBERS_L2 = [
+ SEQUENCE_NUMBER_1,
+ SEQUENCE_NUMBER_2,
+ SEQUENCE_NUMBER_3,
+ SEQUENCE_NUMBER_4,
+ SEQUENCE_NUMBER_5,
+ SEQUENCE_NUMBER_6,
+ ]
+
+
+
+LIST_SHUTTER_COUNT_L2 = [
+ SEQUENCE_NUMBER_3,
+ SEQUENCE_NUMBER_4,
+ SEQUENCE_NUMBER_5,
+ SEQUENCE_NUMBER_6,
+ ]
+
+# Level 1
+LIST_DATE_TIME_L1 = [IMAGE_DATE, TODAY, YESTERDAY]
+
+DICT_DATE_TIME_L1 = {
+ IMAGE_DATE: LIST_IMAGE_DATE_TIME_L2,
+ TODAY: LIST_DATE_TIME_L2,
+ YESTERDAY: LIST_DATE_TIME_L2,
+ ORDER_KEY: LIST_DATE_TIME_L1
+ }
+
+
+LIST_FILENAME_L1 = [NAME_EXTENSION, NAME, EXTENSION, IMAGE_NUMBER]
+
+DICT_FILENAME_L1 = {
+ NAME_EXTENSION: LIST_CASE_L2,
+ NAME: LIST_CASE_L2,
+ EXTENSION: LIST_CASE_L2,
+ IMAGE_NUMBER: LIST_IMAGE_NUMBER_L2,
+ ORDER_KEY: LIST_FILENAME_L1
+ }
+
+
+
+LIST_SUBFOLDER_FILENAME_L1 = [EXTENSION]
+
+DICT_SUBFOLDER_FILENAME_L1 = {
+ EXTENSION: LIST_CASE_L2,
+ ORDER_KEY: LIST_SUBFOLDER_FILENAME_L1
+}
+
+LIST_METADATA_L1 = [APERTURE, ISO, EXPOSURE_TIME, FOCAL_LENGTH,
+ CAMERA_MAKE, CAMERA_MODEL,
+ SHORT_CAMERA_MODEL,
+ SHORT_CAMERA_MODEL_HYPHEN,
+ SERIAL_NUMBER,
+ SHUTTER_COUNT,
+ OWNER_NAME]
+
+DICT_METADATA_L1 = {
+ APERTURE: None,
+ ISO: None,
+ EXPOSURE_TIME: None,
+ FOCAL_LENGTH: None,
+ CAMERA_MAKE: LIST_CASE_L2,
+ CAMERA_MODEL: LIST_CASE_L2,
+ SHORT_CAMERA_MODEL: LIST_CASE_L2,
+ SHORT_CAMERA_MODEL_HYPHEN: LIST_CASE_L2,
+ SERIAL_NUMBER: None,
+ SHUTTER_COUNT: LIST_SHUTTER_COUNT_L2,
+ OWNER_NAME: LIST_CASE_L2,
+ ORDER_KEY: LIST_METADATA_L1
+ }
+
+
+LIST_SEQUENCE_L1 = [
+ DOWNLOAD_SEQ_NUMBER,
+ STORED_SEQ_NUMBER,
+ SESSION_SEQ_NUMBER,
+ SEQUENCE_LETTER
+ ]
+
+DICT_SEQUENCE_L1 = {
+ DOWNLOAD_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2,
+ STORED_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2,
+ SESSION_SEQ_NUMBER: LIST_SEQUENCE_NUMBERS_L2,
+ SEQUENCE_LETTER: LIST_SEQUENCE_LETTER_L2,
+ ORDER_KEY: LIST_SEQUENCE_L1
+ }
+
+
+# Level 0
+
+
+LIST_IMAGE_RENAME_L0 = [DATE_TIME, TEXT, FILENAME, METADATA,
+ SEQUENCES]
+
+
+DICT_IMAGE_RENAME_L0 = {
+ DATE_TIME: DICT_DATE_TIME_L1,
+ TEXT: None,
+ FILENAME: DICT_FILENAME_L1,
+ METADATA: DICT_METADATA_L1,
+ SEQUENCES: DICT_SEQUENCE_L1,
+ ORDER_KEY: LIST_IMAGE_RENAME_L0
+ }
+
+LIST_SUBFOLDER_L0 = [DATE_TIME, TEXT, FILENAME, METADATA, SEPARATOR]
+
+DICT_SUBFOLDER_L0 = {
+ DATE_TIME: DICT_DATE_TIME_L1,
+ TEXT: None,
+ FILENAME: DICT_SUBFOLDER_FILENAME_L1,
+ METADATA: DICT_METADATA_L1,
+ SEPARATOR: None,
+ ORDER_KEY: LIST_SUBFOLDER_L0
+ }
+
+# preference elements that require metadata
+# note there is no need to specify lower level elements if a higher level
+# element is necessary for them to be present to begin with
+METADATA_ELEMENTS = [METADATA, IMAGE_DATE]
+
+# preference elements that are sequence numbers or letters
+SEQUENCE_ELEMENTS = [
+ DOWNLOAD_SEQ_NUMBER,
+ SESSION_SEQ_NUMBER,
+ SUBFOLDER_SEQ_NUMBER,
+ STORED_SEQ_NUMBER,
+ SEQUENCE_LETTER]
+
+# preference elements that do not require metadata and are not fixed
+# as above, there is no need to specify lower level elements if a higher level
+# element is necessary for them to be present to begin with
+DYNAMIC_NON_METADATA_ELEMENTS = [
+ TODAY, YESTERDAY,
+ FILENAME] + SEQUENCE_ELEMENTS
+
+
+
+#the following is what the preferences looked in older versions of the program
+#they are here for reference, and for checking the validity of preferences
+
+USER_INPUT = 'User'
+
+DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7 = 'Downloads today'
+SESSION_SEQ_NUMBER_V_0_0_8_B7 = 'Session sequence number'
+SUBFOLDER_SEQ_NUMBER_V_0_0_8_B7 = 'Subfolder sequence number'
+STORED_SEQ_NUMBER_V_0_0_8_B7 = 'Stored sequence number'
+SEQUENCE_LETTER_V_0_0_8_B7 = 'Sequence letter'
+
+LIST_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 = [
+ SEQUENCE_NUMBER_1,
+ SEQUENCE_NUMBER_2,
+ SEQUENCE_NUMBER_3,
+ SEQUENCE_NUMBER_4,
+ SEQUENCE_NUMBER_5,
+ SEQUENCE_NUMBER_6,
+ ]
+
+DICT_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7 = {
+ SEQUENCE_NUMBER_1: None,
+ SEQUENCE_NUMBER_2: None,
+ SEQUENCE_NUMBER_3: None,
+ SEQUENCE_NUMBER_4: None,
+ SEQUENCE_NUMBER_5: None,
+ SEQUENCE_NUMBER_6: None,
+ ORDER_KEY: LIST_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7
+ }
+
+LIST_SEQUENCE_L1_V_0_0_8_B7 = [USER_INPUT]
+
+DICT_SEQUENCE_L1_V_0_0_8_B7 = {
+ USER_INPUT: DICT_SEQUENCE_NUMBERS_L1_L2_V_0_0_8_B7,
+ ORDER_KEY: LIST_SEQUENCE_L1_V_0_0_8_B7
+ }
+
+LIST_SEQUENCE_LETTER_L1_L1_V_0_0_8_B7 = [
+ UPPERCASE,
+ LOWERCASE
+ ]
+
+DICT_SEQUENCE_LETTER_L1_V_0_0_8_B7 = {
+ UPPERCASE: None,
+ LOWERCASE: None,
+ ORDER_KEY: LIST_SEQUENCE_LETTER_L1_L1_V_0_0_8_B7
+ }
+
+LIST_IMAGE_RENAME_L0_V_0_0_8_B7 = [DATE_TIME, TEXT, FILENAME, METADATA,
+ DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7,
+ SESSION_SEQ_NUMBER_V_0_0_8_B7,
+ SEQUENCE_LETTER_V_0_0_8_B7]
+
+DICT_IMAGE_RENAME_L0_V_0_0_8_B7 = {
+ DATE_TIME: DICT_DATE_TIME_L1,
+ TEXT: None,
+ FILENAME: DICT_FILENAME_L1,
+ METADATA: DICT_METADATA_L1,
+ DOWNLOAD_SEQ_NUMBER_V_0_0_8_B7: None,
+ SESSION_SEQ_NUMBER_V_0_0_8_B7: None,
+ SEQUENCE_LETTER_V_0_0_8_B7: DICT_SEQUENCE_LETTER_L1_V_0_0_8_B7,
+ ORDER_KEY: LIST_IMAGE_RENAME_L0_V_0_0_8_B7
+ }
+
+PREVIOUS_IMAGE_RENAME= {
+ '0.0.8~b7': DICT_IMAGE_RENAME_L0_V_0_0_8_B7,
+ }
+
+
+# Functions to work with above data
+
+def _getPrevPrefs(oldDefs, currentDefs, previousVersion):
+ k = oldDefs.keys()
+ # if there were other defns, we'd need to figure out which one
+ # but currently, there are no others
+ # there will be in future, and this code wil be updated then
+ version_change = pythonifyVersion(k[0])
+ if pythonifyVersion(previousVersion) <= version_change:
+ return oldDefs[k[0]]
+ else:
+ return currentDefs
+
+def _upgradePreferencesToCurrent(prefs, previousVersion):
+ """ checks to see if preferences should be upgraded
+
+ returns True if they were upgraded, and the new prefs
+
+ VERY IMPORTANT: the new prefs will be a new list, not an inplace
+ modification of the existing preferences! Otherwise, the check on
+ assignment in the prefs.py __setattr__ will not work as expected!!
+ """
+ upgraded = False
+ # code to upgrade from <= 0.0.8~b7 to >= 0.0.8~b8
+ p = []
+ for i in range(0, len(prefs), 3):
+ if prefs[i] in [SEQUENCE_LETTER_V_0_0_8_B7, SESSION_SEQ_NUMBER_V_0_0_8_B7]:
+ upgraded = True
+ p.append(SEQUENCES)
+ if prefs[i] == SEQUENCE_LETTER_V_0_0_8_B7:
+ p.append(SEQUENCE_LETTER)
+ p.append(prefs[i+1])
+ else:
+ p.append(SESSION_SEQ_NUMBER)
+ p.append(prefs[i+2])
+ else:
+ p += prefs[i:i+3]
+
+ assert(len(prefs)==len(p))
+ return (upgraded, p)
+
+
+def upgradePreferencesToCurrent(imageRenamePrefs, subfolderPrefs, previousVersion):
+ """Upgrades user preferences to current version
+
+ returns True if the preferences were upgraded"""
+
+ # only check image rename, for now....
+ upgraded, imageRenamePrefs = _upgradePreferencesToCurrent(imageRenamePrefs, previousVersion)
+ return (upgraded, imageRenamePrefs , subfolderPrefs)
+
+def checkPreferencesForValidity(imageRenamePrefs, subfolderPrefs, version=config.version):
+ """Returns true if the passed in preferences are valid"""
+
+ if version == config.version:
+ try:
+ checkPreferenceValid(DICT_SUBFOLDER_L0, subfolderPrefs)
+ checkPreferenceValid(DICT_IMAGE_RENAME_L0, imageRenamePrefs)
+ except:
+ return False
+ return True
+ else:
+ defn = _getPrevPrefs(PREVIOUS_IMAGE_RENAME, DICT_IMAGE_RENAME_L0, version)
+ try:
+ checkPreferenceValid(defn, imageRenamePrefs)
+ checkPreferenceValid(DICT_SUBFOLDER_L0, subfolderPrefs)
+ except:
+ return False
+ return True
+
+def checkPreferenceValid(prefDefinition, prefs, modulo=3):
+ """
+ Checks to see if prefs are valid according to definition.
+
+ prefs is a list of preferences.
+ prefDefinition is a Dict specifying what is valid.
+ modulo is how many list elements are equivalent to one line of preferences.
+
+ Returns True if prefs match with prefDefinition,
+ else raises appropriate error.
+ """
+
+ if (len(prefs) % modulo <> 0) or not prefs:
+ raise PrefLengthError(prefs)
+ else:
+ for i in range(0, len(prefs), modulo):
+ _checkPreferenceValid(prefDefinition, prefs[i:i+modulo])
+
+ return True
+
+def _checkPreferenceValid(prefDefinition, prefs):
+
+ key = prefs[0]
+ value = prefs[1]
+
+
+ if prefDefinition.has_key(key):
+
+ nextPrefDefinition = prefDefinition[key]
+
+ if value == None:
+ # value should never be None, at any time
+ raise PrefValueInvalidError((None, nextPrefDefinition))
+
+ if nextPrefDefinition and not value:
+ raise PrefValueInvalidError((value, nextPrefDefinition))
+
+ if type(nextPrefDefinition) == type({}):
+ return _checkPreferenceValid(nextPrefDefinition, prefs[1:])
+ else:
+ if type(nextPrefDefinition) == type([]):
+ result = value in nextPrefDefinition
+ if not result:
+ raise PrefValueInvalidError((value, nextPrefDefinition))
+ return True
+ elif not nextPrefDefinition:
+ return True
+ else:
+ result = nextPrefDefinition == value
+ if not result:
+ raise PrefKeyValue((value, nextPrefDefinition))
+ return True
+ else:
+ raise PrefKeyError((key, prefDefinition[ORDER_KEY]))
+
+def filterSubfolderPreferences(prefList):
+ """
+ Filters out extraneous preference choices
+ """
+ prefs_changed = False
+ continueCheck = True
+ while continueCheck and prefList:
+ continueCheck = False
+ if prefList[0] == SEPARATOR:
+ # Subfolder preferences should not start with a /
+ prefList = prefList[3:]
+ prefs_changed = True
+ continueCheck = True
+ elif prefList[-3] == SEPARATOR:
+ # Subfolder preferences should not end with a /
+ prefList = prefList[:-3]
+ continueCheck = True
+ prefs_changed = True
+ else:
+ for i in range(0, len(prefList) - 3, 3):
+ if prefList[i] == SEPARATOR and prefList[i+3] == SEPARATOR:
+ # Subfolder preferences should not contain two /s side by side
+ continueCheck = True
+ prefs_changed = True
+ # note we are messing with the contents of the pref list,
+ # must exit loop and try again
+ prefList = prefList[:i] + prefList[i+3:]
+ break
+
+ return (prefs_changed, prefList)
+
+
+class PrefError(Exception):
+ """ base class """
+ def unpackList(self, l):
+ s = ''
+ for i in l:
+ if i <> ORDER_KEY:
+ s += "'" + i + "', "
+ return s[:-2]
+
+ def __str__(self):
+ return self.msg
+
+class PrefKeyError(PrefError):
+ def __init__(self, error):
+ value = error[0]
+ expectedValues = self.unpackList(error[1])
+ self.msg = _("Preference key '%(key)s' is invalid.\nExpected one of %(value)s") % {
+ 'key': value, 'value': expectedValues}
+
+
+class PrefValueInvalidError(PrefKeyError):
+ def __init__(self, error):
+ value = error[0]
+ self.msg = _("Preference value '%(value)s' is invalid") % {'value': value}
+
+class PrefLengthError(PrefError):
+ def __init__(self, error):
+ self.msg = _("These preferences are not well formed:") % self.unpackList(error) + "\n %s"
+
+class PrefValueKeyComboError(PrefError):
+ def __init__(self, error):
+ self.msg = error
+
+
+def convertDateForStrftime(dateTimeUserChoice):
+ try:
+ return DATE_TIME_CONVERT[LIST_DATE_TIME_L2.index(dateTimeUserChoice)]
+ except:
+ raise PrefValueInvalidError(dateTimeUserChoice)
+
+
+class Comboi18n(gtk.ComboBox):
+ """ very simple i18n version of the venerable combo box
+ with one column displayed to the user.
+
+ This combo box has two columns:
+ 1. the first contains the actual value and is invisible
+ 2. the second contains the translation of the first column, and this is what
+ the users sees
+ """
+ def __init__(self):
+ liststore = gtk.ListStore(str, str)
+ gtk.ComboBox.__init__(self, liststore)
+ cell = gtk.CellRendererText()
+ self.pack_start(cell, True)
+ self.add_attribute(cell, 'text', 1)
+
+ def append_text(self, text):
+ model = self.get_model()
+ model.append((text, _(text)))
+
+ def get_active_text(self):
+ model = self.get_model()
+ active = self.get_active()
+ if active < 0:
+ return None
+ return model[active][0]
+
+class ImageRenamePreferences:
+ def __init__(self, prefList, parent, fileSequenceLock=None, sequences=None):
+ """
+ Exception raised if preferences are invalid.
+
+ This should be caught by calling class."""
+
+ self.parent = parent
+ self.prefList = prefList
+
+ # use variables for determining sequence numbers
+ # there are two possibilities:
+ # 1. this code is being called while being run from within a copy photos process
+ # 2. it's being called from within the preferences dialog window
+
+ self.fileSequenceLock = fileSequenceLock
+ self.sequences = sequences
+
+ # derived classes will have their own definitions, do not overwrite
+ if not hasattr(self, "prefsDefnL0"):
+ self.prefsDefnL0 = DICT_IMAGE_RENAME_L0
+ self.defaultPrefs = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE]
+ self.defaultRow = self.defaultPrefs
+ self.stripForwardSlash = True
+
+
+
+ def checkPrefsForValidity(self):
+ """
+ Checks image preferences validity
+ """
+
+ return checkPreferenceValid(self.prefsDefnL0, self.prefList)
+
+ def formatPreferencesForPrettyPrint(self):
+ """ returns a string useful for printing the preferences"""
+
+ v = ''
+
+ for i in range(0, len(self.prefList), 3):
+ s = "%s: " % self.prefList[i]
+ if self.prefList[i+1]:
+ s = "%s%s" % (s, self.prefList[i+1])
+ if self.prefList[i+2]:
+ s = "%s (%s)" % (s, self.prefList[i+2])
+
+ v += s + "\n"
+ return v
+
+
+ def _getDateComponent(self):
+ """
+ Returns portion of new image / subfolder name based on date time
+ """
+
+ problem = None
+ if self.L1 == IMAGE_DATE:
+ if self.L2 == SUBSECONDS:
+ d = self.photo.subSeconds()
+ problem = _("Subsecond metadata not present in image")
+ else:
+ d = self.photo.dateTime(missing=None)
+ problem = _("%s metadata is not present in image") % self.L1.lower()
+ elif self.L1 == TODAY:
+ d = datetime.datetime.now()
+ elif self.L1 == YESTERDAY:
+ delta = datetime.timedelta(days = 1)
+ d = datetime.datetime.now() - delta
+ else:
+ raise("Date options invalid")
+
+ if d:
+ if self.L2 <> SUBSECONDS:
+ try:
+ return (d.strftime(convertDateForStrftime(self.L2)), None)
+ except:
+ v = ''
+ problem = _('Error in date time component. Value %s appears invalid') % d
+ return (v, problem)
+ else:
+ return (d, None)
+ else:
+ return ('', problem)
+
+ def _getFilenameComponent(self):
+ """
+ Returns portion of new image / subfolder name based on the file name
+ """
+
+ name, extension = os.path.splitext(self.existingFilename)
+ problem = None
+
+ if self.L1 == NAME_EXTENSION:
+ filename = self.existingFilename
+ elif self.L1 == NAME:
+ filename = name
+ elif self.L1 == EXTENSION:
+ if extension:
+ if not self.stripInitialPeriodFromExtension:
+ # keep the period / dot of the extension, so the user does not
+ # need to manually specify it
+ filename = extension
+ else:
+ # having the period when this is used as a part of a subfolder name
+ # is a bad idea!
+ filename = extension[1:]
+ else:
+ filename = ""
+ problem = _("extension was specified but image name has no extension")
+ elif self.L1 == IMAGE_NUMBER:
+ n = re.search("(?P<image_number>[0-9]+$)", name)
+ if not n:
+ problem = _("image number was specified but image filename has no number")
+ else:
+ image_number = n.group("image_number")
+
+ if self.L2 == IMAGE_NUMBER_ALL:
+ filename = image_number
+ elif self.L2 == IMAGE_NUMBER_1:
+ filename = image_number[-1]
+ elif self.L2 == IMAGE_NUMBER_2:
+ filename = image_number[-2:]
+ elif self.L2 == IMAGE_NUMBER_3:
+ filename = image_number[-3:]
+ elif self.L2 == IMAGE_NUMBER_4:
+ filename = image_number[-4:]
+ else:
+ raise TypeError("Incorrect filename option")
+
+ if self.L2 == UPPERCASE:
+ filename = filename.upper()
+ elif self.L2 == LOWERCASE:
+ filename = filename.lower()
+
+ return (filename, problem)
+
+ def _getMetadataComponent(self):
+ """
+ Returns portion of new image / subfolder name based on the metadata
+
+ Note: date time metadata found in _getDateComponent()
+ """
+
+ problem = None
+ if self.L1 == APERTURE:
+ v = self.photo.aperture()
+ elif self.L1 == ISO:
+ v = self.photo.iso()
+ elif self.L1 == EXPOSURE_TIME:
+ v = self.photo.exposureTime(alternativeFormat=True)
+ elif self.L1 == FOCAL_LENGTH:
+ v = self.photo.focalLength()
+ elif self.L1 == CAMERA_MAKE:
+ v = self.photo.cameraMake()
+ elif self.L1 == CAMERA_MODEL:
+ v = self.photo.cameraModel()
+ elif self.L1 == SHORT_CAMERA_MODEL:
+ v = self.photo.shortCameraModel()
+ elif self.L1 == SHORT_CAMERA_MODEL_HYPHEN:
+ v = self.photo.shortCameraModel(includeCharacters = "\-")
+ elif self.L1 == SERIAL_NUMBER:
+ v = self.photo.cameraSerial()
+ elif self.L1 == SHUTTER_COUNT:
+ v = self.photo.shutterCount()
+ if v:
+ v = int(v)
+ padding = LIST_SHUTTER_COUNT_L2.index(self.L2) + 3
+ formatter = '%0' + str(padding) + "i"
+ v = formatter % v
+
+ elif self.L1 == OWNER_NAME:
+ v = self.photo.ownerName()
+ else:
+ raise TypeError("Invalid metadata option specified")
+ if self.L1 in [CAMERA_MAKE, CAMERA_MODEL, SHORT_CAMERA_MODEL,
+ SHORT_CAMERA_MODEL_HYPHEN, OWNER_NAME]:
+ if self.L2 == UPPERCASE:
+ v = v.upper()
+ elif self.L2 == LOWERCASE:
+ v = v.lower()
+ if not v:
+ if self.L1 <> ISO:
+ md = self.L1.lower()
+ else:
+ md = ISO
+ problem = _("%s metadata is not present in image") % md
+ return (v, problem)
+
+
+ def _formatSequenceNo(self, value, amountToPad):
+ padding = LIST_SEQUENCE_NUMBERS_L2.index(amountToPad) + 1
+ formatter = '%0' + str(padding) + "i"
+ return formatter % value
+
+
+ def _calculateLetterSequence(self, sequence):
+
+ def _letters(x):
+ """
+ Adapted from algorithm at http://en.wikipedia.org/wiki/Hexavigesimal
+ """
+ v = ''
+ while x > 25:
+ r = x % 26
+ x= x / 26 - 1
+ v = string.lowercase[r] + v
+ v = string.lowercase[x] + v
+
+ return v
+
+
+ v = _letters(sequence)
+ if self.L2 == UPPERCASE:
+ v = v.upper()
+
+ return v
+
+ def _getSubfolderSequenceNo(self):
+ """
+ Add a sequence number to the filename
+
+ * Sequence numbering is per subfolder
+ * Assume the user might actually have a (perhaps odd) reason to have more
+ than one subfolder sequence number in the same file name
+ """
+
+ problem = None
+ self.subfolderSeqNoInstanceInFilename += 1
+
+ if self.downloadSubfolder:
+ subfolder = self.downloadSubfolder + str(self.subfolderSeqNoInstanceInFilename)
+ else:
+ subfolder = "__subfolder__" + str(self.subfolderSeqNoInstanceInFilename)
+
+ if self.fileSequenceLock:
+ with self.fileSequenceLock:
+ v = self.sequenceNos.calculate(subfolder)
+ v = self.formatSequenceNo(v, self.L1)
+ else:
+ v = self.sequenceNos.calculate(subfolder)
+ v = self.formatSequenceNo(v, self.L1)
+
+ return (v, problem)
+
+ def _getSessionSequenceNo(self):
+ problem = None
+ v = self._formatSequenceNo(self.sequences.getSessionSequenceNoUsingCounter(self.sequenceCounter), self.L2)
+ return (v, problem)
+
+ def _getDownloadsTodaySequenceNo(self):
+ problem = None
+
+ v = self._formatSequenceNo(self.sequences.getDownloadsTodayUsingCounter(self.sequenceCounter), self.L2)
+
+ return (v, problem)
+
+ def _getStoredSequenceNo(self):
+ problem = None
+ v = self._formatSequenceNo(self.sequences.getStoredSequenceNoUsingCounter(self.sequenceCounter), self.L2)
+
+ return (v, problem)
+
+ def _getSequenceLetter(self):
+
+ problem = None
+ v = self._calculateLetterSequence(self.sequences.getSequenceLetterUsingCounter(self.sequenceCounter))
+ return (v, problem)
+
+ def _getSequencesComponent(self):
+ problem = None
+ if self.L1 == DOWNLOAD_SEQ_NUMBER:
+ return self._getDownloadsTodaySequenceNo()
+ elif self.L1 == SESSION_SEQ_NUMBER:
+ return self._getSessionSequenceNo()
+ elif self.L1 == SUBFOLDER_SEQ_NUMBER:
+ return self._getSubfolderSequenceNo()
+ elif self.L1 == STORED_SEQ_NUMBER:
+ return self._getStoredSequenceNo()
+ elif self.L1 == SEQUENCE_LETTER:
+ return self._getSequenceLetter()
+
+ def _getComponent(self):
+ try:
+ if self.L0 == DATE_TIME:
+ return self._getDateComponent()
+ elif self.L0 == TEXT:
+ return (self.L1, None)
+ elif self.L0 == FILENAME:
+ return self._getFilenameComponent()
+ elif self.L0 == METADATA:
+ return self._getMetadataComponent()
+ elif self.L0 == SEQUENCES:
+ return self._getSequencesComponent()
+ elif self.L0 == SEPARATOR:
+ return (os.sep, None)
+ except:
+ v = ""
+ problem = _("error generating name with component %s") % self.L2
+ return (v, problem)
+
+ def _getValuesFromList(self):
+ for i in range(0, len(self.prefList), 3):
+ yield (self.prefList[i], self.prefList[i+1], self.prefList[i+2])
+
+
+ def _generateName(self, photo, existingFilename, stripCharacters, subfolder, stripInitialPeriodFromExtension, sequence):
+ self.photo = photo
+ self.existingFilename = existingFilename
+ self.stripInitialPeriodFromExtension = stripInitialPeriodFromExtension
+
+ name = ''
+ problem = ''
+
+ #the subfolder in which the image will be downloaded to
+ self.downloadSubfolder = subfolder
+
+ self.sequenceCounter = sequence
+
+ for self.L0, self.L1, self.L2 in self._getValuesFromList():
+ v, p = self._getComponent()
+ if v:
+ name += v
+ if p:
+ problem += p + "; "
+
+ if problem:
+ # remove final semicolon and space
+ problem = problem[:-2] + '.'
+
+ if stripCharacters:
+ for c in r'\:*?"<>|':
+ name = name.replace(c, '')
+
+ if self.stripForwardSlash:
+ name = name.replace('/', '')
+
+ return (name, problem)
+
+ def generateNameUsingPreferences(self, photo, existingFilename=None,
+ stripCharacters = False, subfolder=None,
+ stripInitialPeriodFromExtension=False,
+ sequencesPreliminary = True):
+ """
+ Generate a filename for the photo in string format based on user prefs.
+
+ Returns a tuple of two strings:
+ - the name
+ - any problems generating the name. If blank, there were no problems
+ """
+
+ if self.sequences:
+ if sequencesPreliminary:
+ sequence = self.sequences.getPrelimSequence()
+ else:
+ sequence = self.sequences.getFinalSequence()
+ else:
+ sequence = 0
+
+ return self._generateName(photo, existingFilename, stripCharacters, subfolder,
+ stripInitialPeriodFromExtension, sequence)
+
+ def generateNameSequencePossibilities(self, photo, existingFilename,
+ stripCharacters=False, subfolder=None,
+ stripInitialPeriodFromExtension=False):
+
+ """ Generates the possible image names using the sequence numbers / letter possibilities"""
+
+ for sequence in self.sequences.getSequencePossibilities():
+ yield self._generateName(photo, existingFilename, stripCharacters , subfolder,
+ stripInitialPeriodFromExtension, sequence)
+
+ def filterPreferences(self):
+ """
+ Filters out extraneous preference choices
+ Expected to be implemented in derived classes when needed
+ """
+ pass
+
+ def needImageMetaDataToCreateUniqueName(self):
+ """
+ Returns True if an image's metadata is essential to properly generate a unique image name
+
+ Image names should be unique. Some images may not have metadata. If
+ only non-dynamic components make up the rest of an image name
+ (e.g. text specified by the user), then relying on metadata will likely
+ produce duplicate names.
+
+ File extensions are not considered dynamic.
+
+ This is NOT a general test to see if unique filenames can be generated. It is a test
+ to see if an image's metadata is needed.
+ """
+ hasMD = hasDynamic = False
+
+ for e in METADATA_ELEMENTS:
+ if e in self.prefList:
+ hasMD = True
+ break
+
+ if hasMD:
+ for e in DYNAMIC_NON_METADATA_ELEMENTS:
+ if e in self.prefList:
+ if e == FILENAME and (NAME_EXTENSION in self.prefList or
+ NAME in self.prefList or
+ IMAGE_NUMBER in self.prefList):
+ hasDynamic = True
+ break
+
+ if hasMD and not hasDynamic:
+ return True
+ else:
+ return False
+
+ def usesSequenceElements(self):
+ """ Returns true if any sequence numbers or letters are used to generate the filename """
+
+ for e in SEQUENCE_ELEMENTS:
+ if e in self.prefList:
+ return True
+
+ return False
+
+ def usesTheSequenceElement(self, e):
+ """ Returns true if a stored sequence number is used to generate the filename """
+ return e in self.prefList
+
+
+ def _createCombo(self, choices):
+ combobox = Comboi18n()
+ for text in choices:
+ combobox.append_text(text)
+ return combobox
+
+ def getDefaultRow(self):
+ """
+ returns a list of default widgets
+ """
+ return self.getWidgetsBasedOnUserSelection(self.defaultRow)
+
+ def _getPreferenceWidgets(self, prefDefinition, prefs, widgets):
+ key = prefs[0]
+ value = prefs[1]
+
+ # supply a default value if the user has not yet chosen a value!
+ if not key:
+ key = prefDefinition[ORDER_KEY][0]
+
+ if not key in prefDefinition:
+ raise PrefKeyError((key, prefDefinition.keys()))
+
+
+ list0 = prefDefinition[ORDER_KEY]
+
+ # the first widget will always be a combo box
+ widget0 = self._createCombo(list0)
+ widget0.set_active(list0.index(key))
+
+ widgets.append(widget0)
+
+ if key == TEXT:
+ widget1 = gtk.Entry()
+ widget1.set_text(value)
+
+ widgets.append(widget1)
+ widgets.append(None)
+ return
+ elif key == SEPARATOR:
+ widgets.append(None)
+ widgets.append(None)
+ return
+ else:
+ nextPrefDefinition = prefDefinition[key]
+ if type(nextPrefDefinition) == type({}):
+ return self._getPreferenceWidgets(nextPrefDefinition,
+ prefs[1:],
+ widgets)
+ else:
+ if type(nextPrefDefinition) == type([]):
+ widget1 = self._createCombo(nextPrefDefinition)
+ if not value:
+ value = nextPrefDefinition[0]
+ try:
+ widget1.set_active(nextPrefDefinition.index(value))
+ except:
+ raise PrefValueInvalidError((value, nextPrefDefinition))
+
+ widgets.append(widget1)
+ else:
+ widgets.append(None)
+
+ def getWidgetsBasedOnPreferences(self):
+ """
+ Yields a list of widgets and their callbacks based on the users preferences.
+
+ This list is equivalent to one row of preferences when presented to the
+ user in the Plus Minus Table.
+ """
+
+ for L0, L1, L2 in self._getValuesFromList():
+ prefs = [L0, L1, L2]
+ widgets = []
+ self._getPreferenceWidgets(self.prefsDefnL0, prefs, widgets)
+ yield widgets
+
+
+ def getWidgetsBasedOnUserSelection(self, selection):
+ """
+ Returns a list of widgets and their callbacks based on what the user has selected.
+
+ Selection is the values the user has chosen thus far in comboboxes.
+ It determines the contents of the widgets returned.
+ It should be a list of three values, with None for values not chosen.
+ For values which are None, the first value in the preferences
+ definition is chosen.
+
+ """
+ widgets = []
+
+ self._getPreferenceWidgets(self.prefsDefnL0, selection, widgets)
+ return widgets
+
+class SubfolderPreferences(ImageRenamePreferences):
+ def __init__(self, prefList, parent):
+ self.prefsDefnL0 = DICT_SUBFOLDER_L0
+ self.defaultPrefs = DEFAULT_SUBFOLDER_PREFS
+ self.defaultRow = [DATE_TIME, IMAGE_DATE, LIST_DATE_TIME_L2[0]]
+ self.stripForwardSlash = False
+ ImageRenamePreferences.__init__(self, prefList, parent)
+
+ def generateNameUsingPreferences(self, photo, existingFilename=None,
+ stripCharacters = False):
+ """
+ Generate a filename for the photo in string format based on user prefs.
+
+ Returns a tuple of two strings:
+ - the name
+ - any problems generating the name. If blank, there were no problems
+ """
+
+ subfolders, problem = ImageRenamePreferences.generateNameUsingPreferences(
+ self, photo,
+ existingFilename, stripCharacters, stripInitialPeriodFromExtension=True)
+ # subfolder value must never start with a separator, or else any
+ # os.path.join function call will fail to join a subfolder to its
+ # parent folder
+ if subfolders:
+ if subfolders[0] == os.sep:
+ subfolders = subfolders[1:]
+
+ return (subfolders, problem)
+
+ def filterPreferences(self):
+ filtered, prefList = filterSubfolderPreferences(self.prefList)
+ if filtered:
+ self.prefList = prefList
+
+ def needMetaDataToCreateUniqueName(self):
+ """
+ Returns True if metadata is essential to properly generate subfolders
+
+ This will be the case if the only components are metadata and separators
+ """
+
+ for e in self.prefList:
+ if (not e) and ((e not in METADATA_ELEMENTS) or (e <> SEPARATOR)):
+ return True
+
+ return False
+
+
+
+
+ def checkPrefsForValidity(self):
+ """
+ Checks subfolder preferences validity above and beyond image name checks.
+
+ See parent method for full description.
+
+ Subfolders have additional requirments to that of image names.
+ """
+ v = ImageRenamePreferences.checkPrefsForValidity(self)
+ if v:
+ # peform additional checks:
+ # 1. do not start with a separator
+ # 2. do not end with a separator
+ # 3. do not have two separators in a row
+ # these three rules will ensure something else other than a
+ # separator is specified
+ L1s = []
+ for i in range(0, len(self.prefList), 3):
+ L1s.append(self.prefList[i])
+
+ if L1s[0] == SEPARATOR:
+ raise PrefValueKeyComboError(_("Subfolder preferences should not start with a %s") % os.sep)
+ elif L1s[-1] == SEPARATOR:
+ raise PrefValueKeyComboError(_("Subfolder preferences should not end with a %s") % os.sep)
+ else:
+ for i in range(len(L1s) - 1):
+ if L1s[i] == SEPARATOR and L1s[i+1] == SEPARATOR:
+ raise PrefValueKeyComboError(_("Subfolder preferences should not contain two %s one after the other") % os.sep)
+ return v
+
+
+class Sequences:
+ """ Holds sequence numbers and letters used in generating filenames"""
+ def __init__(self, downloadsToday, storedSequenceNo):
+
+
+ self.subfolderSequenceNo = {}
+ self.sessionSequenceNo = 1
+ self.sequenceLetter = 0
+
+ self.setUseOfSequenceElements(False, False)
+
+ self.assignedSequenceCounter = 1
+ self.reset(downloadsToday, storedSequenceNo)
+
+ def setUseOfSequenceElements(self, usesSessionSequenceNo, usesSequenceLetter):
+ self.usesSessionSequenceNo = usesSessionSequenceNo
+ self.usesSequenceLetter = usesSequenceLetter
+
+ def reset(self, downloadsToday, storedSequenceNo):
+ self.downloadsToday = downloadsToday
+ self.downloadsTodayOffset = 0
+ self.storedSequenceNo = storedSequenceNo
+ if self.usesSessionSequenceNo:
+ self.sessionSequenceNo = self.sessionSequenceNo + self.assignedSequenceCounter - 1
+ if self.usesSequenceLetter:
+ self.sequenceLetter = self.sequenceLetter + self.assignedSequenceCounter - 1
+ self.doNotAddToPool = False
+ self.pool = []
+ self.poolSequenceCounter = 0
+ self.assignedSequenceCounter = 1
+
+ def getPrelimSequence(self):
+ if self.doNotAddToPool:
+ self.doNotAddToPool = False
+ else:
+ # increment pool sequence number
+ self.poolSequenceCounter += 1
+ self.pool.append(self.poolSequenceCounter)
+
+ return self.poolSequenceCounter
+
+ def getFinalSequence(self):
+ # get oldest queue value
+ # remove from queue or flag it should be removed
+
+ return self.assignedSequenceCounter
+
+ def getSequencePossibilities(self):
+ for i in self.pool:
+ yield i
+
+ def getSessionSequenceNo(self):
+ return self.sessionSequenceNo + self.assignedSequenceCounter - 1
+
+ def getSessionSequenceNoUsingCounter(self, counter):
+ return self.sessionSequenceNo + counter - 1
+
+ def setSessionSequenceNo(self, value):
+ self.sessionSequenceNo = value
+
+ def setStoredSequenceNo(self, value):
+ self.storedSequenceNo = value
+
+ def getDownloadsTodayUsingCounter(self, counter):
+ return self.downloadsToday + counter - self.downloadsTodayOffset
+
+ def setDownloadsToday(self, value):
+ self.downloadsToday = value
+ self.downloadsTodayOffset = self.assignedSequenceCounter - 1
+
+ def getStoredSequenceNoUsingCounter(self, counter):
+ return self.storedSequenceNo + counter
+
+ def getSequenceLetterUsingCounter(self, counter):
+ return self.sequenceLetter + counter - 1
+
+ def imageCopyFailed(self):
+ self.doNotAddToPool = True
+
+ def imageCopySucceeded(self):
+ self.increment()
+
+ def increment(self, subfolder=None):
+ assert(self.assignedSequenceCounter == self.pool[0])
+ self.assignedSequenceCounter += 1
+ self.pool = self.pool[1:]
+
+
+
+
+if __name__ == '__main__':
+ import sys
+ import os.path
+ from metadata import MetaData
+
+ if False:
+ if (len(sys.argv) != 2):
+ print 'Usage: ' + sys.argv[0] + ' path/to/photo/containing/metadata'
+ sys.exit(1)
+ else:
+ p0 = [FILENAME, NAME_EXTENSION, ORIGINAL_CASE]
+ p1 = [FILENAME, NAME_EXTENSION, LOWERCASE]
+ p2 = [METADATA, APERTURE, None]
+ p3 = [FILENAME, IMAGE_NUMBER, IMAGE_NUMBER_ALL]
+ p4 = [METADATA, CAMERA_MODEL, ORIGINAL_CASE]
+ p5 = [TEXT, '-', None]
+ p6 = [TEXT, 'Job', None]
+
+ p = [p0, p1, p2, p3, p4]
+ p = [p6 + p5 + p2 + p5 + p3]
+
+ d0 = [DATE_TIME, IMAGE_DATE, 'YYYYMMDD']
+ d1 = [DATE_TIME, IMAGE_DATE, 'HHMMSS']
+ d2 = [DATE_TIME, IMAGE_DATE, SUBSECONDS]
+
+ d = [d0 + d1 + d2]
+
+ fullpath = sys.argv[1]
+ path, filename = os.path.split(fullpath)
+
+ m = MetaData(fullpath)
+ m.readMetadata()
+
+ for pref in p:
+ i = ImageRenamePreferences(pref, None)
+ print i.generateNameUsingPreferences(m, filename)
+
+ for pref in d:
+ i = ImageRenamePreferences(pref, None)
+ print i.generateNameUsingPreferences(m, filename)
+ else:
+ prefs = [SEQUENCES, SESSION_SEQ_NUMBER, SEQUENCE_NUMBER_3]
+# prefs = ['Filename2', NAME_EXTENSION, UPPERCASE]
+ print checkPreferenceValid(DICT_IMAGE_RENAME_L0, prefs)
diff --git a/rapid/renamesubfolderprefstest.py b/rapid/renamesubfolderprefstest.py
new file mode 100644
index 0000000..a689c5c
--- /dev/null
+++ b/rapid/renamesubfolderprefstest.py
@@ -0,0 +1,190 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import unittest
+
+from renamesubfolderprefs import *
+
+class PreferenceTest (unittest.TestCase):
+ image_test = ( [TEXT, '', ''],
+ [DATE_TIME, IMAGE_DATE, 'YYYYMMDD'],
+ [METADATA, APERTURE, ''],
+ [FILENAME, NAME_EXTENSION, UPPERCASE],
+ )
+ subfolder_test = ( [TEXT, '', ''],
+ [DATE_TIME, IMAGE_DATE, 'HHMM'],
+ [METADATA, SHORT_CAMERA_MODEL_HYPHEN,
+ LOWERCASE],
+ [SEPARATOR, '', ''],
+ [FILENAME, EXTENSION, LOWERCASE]
+ )
+
+ trueMetadataTest = ([FILENAME, EXTENSION, LOWERCASE, TEXT, '', '', METADATA, APERTURE, ''], [METADATA, APERTURE, '', TEXT, '', '', FILENAME, EXTENSION, LOWERCASE], )
+
+ falseMetadataTest = ([FILENAME, EXTENSION, LOWERCASE, METADATA, APERTURE, '', FILENAME, NAME, LOWERCASE],
+ [FILENAME, NAME, LOWERCASE, FILENAME, EXTENSION, LOWERCASE],
+ [FILENAME, NAME_EXTENSION, LOWERCASE, FILENAME, EXTENSION, LOWERCASE],
+ [FILENAME, NAME, LOWERCASE, FILENAME, METADATA, EXPOSURE_TIME, '', IMAGE_NUMBER, IMAGE_NUMBER_ALL, FILENAME, EXTENSION, LOWERCASE], )
+
+ sequences_test = ([SEQUENCES, SESSION_SEQ_NUMBER, SEQUENCE_NUMBER_3],
+ [FILENAME, NAME, LOWERCASE, SEQUENCES, DOWNLOAD_SEQ_NUMBER, SEQUENCE_NUMBER_1,
+ FILENAME, EXTENSION, UPPERCASE],
+ [METADATA, APERTURE, '', SEQUENCES, STORED_SEQ_NUMBER, SEQUENCE_NUMBER_5,
+ FILENAME, EXTENSION, UPPERCASE], )
+
+ def testPrefImageList(self):
+ for pref in self.image_test:
+ result = checkPreferenceValid(DICT_IMAGE_RENAME_L0, pref)
+ self.assertEqual(result, True)
+
+ def testSequencesList(self):
+ for pref in self.sequences_test:
+ result = checkPreferenceValid(DICT_IMAGE_RENAME_L0, pref)
+ self.assertEqual(result, True)
+
+ def testNeedImageMetaDataToCreateUniqueName(self):
+ for i in self.trueMetadataTest:
+ p = ImageRenamePreferences(i, None)
+ result = p.needImageMetaDataToCreateUniqueName()
+ self.assertEqual(result, True)
+
+ for i in self.falseMetadataTest:
+ p = ImageRenamePreferences(i, None)
+ result = p.needImageMetaDataToCreateUniqueName()
+ self.assertEqual(result, False)
+
+
+
+ def testLargePrefList(self):
+ prefList = []
+ for pref in self.image_test:
+ for l in pref:
+ prefList.append(l)
+
+ result = checkPreferenceValid(DICT_IMAGE_RENAME_L0, prefList)
+ self.assertEqual(result, True)
+
+ def testPrefSubfolderList(self):
+ for pref in self.subfolder_test:
+ result = checkPreferenceValid(DICT_SUBFOLDER_L0, pref)
+ self.assertEqual(result, True)
+
+ def testDateTimeL2Length(self):
+ self.assertEqual(len(LIST_DATE_TIME_L2), len(DATE_TIME_CONVERT))
+
+ def testDateTimeL2Conversion(self):
+ self.assertEqual(convertDateForStrftime('YY'), '%y')
+
+
+
+class BadPreferences(unittest.TestCase):
+ bad_image_key = ( [TEXT, '', '',
+ DATE_TIME, IMAGE_DATE, 'YYYYMMDD',
+ METADATA, APERTURE, '',
+ FILENAME, NAME_EXTENSION, UPPERCASE,
+ 'Filename2', NAME_EXTENSION, UPPERCASE],
+ )
+ bad_image_value = ( [DATE_TIME, TODAY, IMAGE_NUMBER_ALL],
+ [METADATA, CAMERA_MAKE, IMAGE_NUMBER_4],
+ [DATE_TIME, IMAGE_DATE, None],
+ [DATE_TIME, IMAGE_DATE, ''],
+ [DATE_TIME, None, None],
+ [DATE_TIME, '', ''],
+ )
+
+ bad_subfolder_key = ([FILENAME, NAME_EXTENSION, UPPERCASE],)
+
+ bad_subfolder_key2 = ( [TEXT, '', '',
+ DATE_TIME, IMAGE_DATE, 'HHMM',
+ METADATA, SHORT_CAMERA_MODEL_HYPHEN,
+ LOWERCASE,
+ SEPARATOR, '', '',
+ 'Filename-bad', EXTENSION, LOWERCASE],
+ )
+
+ bad_subfolder_value = ( [FILENAME, None, None],
+ [FILENAME, '', ''],)
+
+ bad_length = ([], [DATE_TIME, TODAY], [DATE_TIME])
+
+ bad_dt_conversion = ('HHYY', 'YYSS')
+
+ bad_subfolder_combos = ([SEPARATOR, '', ''],
+ [FILENAME, EXTENSION, UPPERCASE,
+ SEPARATOR, '', ''],
+ [FILENAME, EXTENSION, UPPERCASE,
+ SEPARATOR, '', '',
+ SEPARATOR, '', '',
+ FILENAME, EXTENSION, UPPERCASE
+ ],
+ [SEPARATOR, '', '',
+ SEPARATOR, '', '',
+ SEPARATOR, '', '',
+ SEPARATOR, '', ''
+ ]
+ )
+
+ def testBadImageKey(self):
+ for pref in self.bad_image_key:
+ self.assertRaises(PrefKeyError, checkPreferenceValid,
+ DICT_IMAGE_RENAME_L0,
+ pref)
+
+ def testBadImageValue(self):
+ for pref in self.bad_image_value:
+ self.assertRaises(PrefValueInvalidError, checkPreferenceValid,
+ DICT_IMAGE_RENAME_L0,
+ pref)
+
+ def testBadSubfolderKey(self):
+ for pref in self.bad_subfolder_key:
+ self.assertRaises(PrefKeyError, checkPreferenceValid,
+ DICT_SUBFOLDER_L0,
+ pref)
+
+ for pref in self.bad_subfolder_key2:
+ self.assertRaises(PrefKeyError, checkPreferenceValid,
+ DICT_SUBFOLDER_L0,
+ pref)
+
+
+ def testBadSubfolderValue(self):
+ for pref in self.bad_subfolder_value:
+ self.assertRaises(PrefValueInvalidError, checkPreferenceValid,
+ DICT_SUBFOLDER_L0,
+ pref)
+
+ def testBadLength(self):
+ for pref in self.bad_length:
+ self.assertRaises(PrefLengthError, checkPreferenceValid,
+ DICT_IMAGE_RENAME_L0,
+ pref)
+ def testBadDTConversion(self):
+ for pref in self.bad_dt_conversion:
+ self.assertRaises(PrefValueInvalidError, convertDateForStrftime,
+ pref)
+
+ def testBadSubfolderCombo(self):
+
+ for pref in self.bad_subfolder_combos:
+ s = SubfolderPreferences(pref, self)
+ self.assertRaises(PrefValueKeyComboError, s.checkPrefsForValidity)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/rapid/tableplusminus.py b/rapid/tableplusminus.py
new file mode 100644
index 0000000..ab7e7c1
--- /dev/null
+++ b/rapid/tableplusminus.py
@@ -0,0 +1,284 @@
+#!/usr/bin/python
+# -*- coding: latin1 -*-
+
+### Copyright (C) 2007, 2008, 2009 Damon Lynch <damonlynch@gmail.com>
+
+### This program is free software; you can redistribute it and/or modify
+### it under the terms of the GNU General Public License as published by
+### the Free Software Foundation; either version 2 of the License, or
+### (at your option) any later version.
+
+### This program is distributed in the hope that it will be useful,
+### but WITHOUT ANY WARRANTY; without even the implied warranty of
+### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+### GNU General Public License for more details.
+
+### You should have received a copy of the GNU General Public License
+### along with this program; if not, write to the Free Software
+### Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# import gtk.gdk as gdk
+import sys
+try:
+ import pygtk
+ pygtk.require("2.0")
+except:
+ pass
+try:
+ import gtk
+except:
+ sys.exit(1)
+
+import higdefaults as hd
+
+class TablePlusMinus(gtk.Table):
+ """
+ A regular gtk table which allows users to add and delete rows to the table.
+
+ Users add and delete rows by using plus and minus buttons.
+ The buttons (minus first) are in the two rightmost colums.
+ The user can never delete a table so it has no rows.
+ """
+
+ debug = False # if True, then debugging info for the developer is displayed
+ def __init__(self, rows=1, columns=1, homogeneous=False):
+ if not self.debug:
+ gtk.Table.__init__(self, rows, columns + 2, homogeneous)
+ self.extraCols = 2 # representing minus and plus buttons
+ else:
+ gtk.Table.__init__(self, rows, columns + 3, homogeneous)
+ self.extraCols = 3 # representing minus and plus buttons, and info label
+
+ # no of columns NOT including the + and - buttons
+ self.pm_noColumns = columns
+ # how many rows there are in the gtk.Table
+ self.pm_noRows = rows
+ # list of widgets in the gtk.Table
+ self.pm_rows = []
+ # dict of callback ids for minus and plus buttons
+ self.pm_callbacks = {}
+
+ #spacing of controls
+ for i in range(columns-1):
+ self.set_col_spacing(i, hd.CONTROL_IN_TABLE_SPACE)
+ self.set_col_spacing(columns-1, hd.CONTROL_IN_TABLE_SPACE*2)
+ self.set_col_spacing(columns, hd.CONTROL_IN_TABLE_SPACE)
+ if self.debug:
+ self.set_col_spacing(columns+1, hd.CONTROL_IN_TABLE_SPACE)
+ self.set_row_spacings(hd.CONTROL_IN_TABLE_SPACE)
+
+ def _setMinusButtonSensitivity(self):
+ button = self.pm_rows[0][self.pm_noColumns]
+ if len(self.pm_rows) == 1:
+ button.set_sensitive(False)
+ else:
+ button.set_sensitive(True)
+
+ def _createMinusPlusButtons(self, rowPosition):
+ plus_button = gtk.Button()
+ plus_button.set_image(gtk.image_new_from_stock(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU))
+ self._createCallback(plus_button, rowPosition, 'clicked', self.on_plus_button_clicked)
+ minus_button = gtk.Button()
+ minus_button.set_image(gtk.image_new_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_MENU))
+ self._createCallback(minus_button, rowPosition, 'clicked', self.on_minus_button_clicked)
+
+ return minus_button, plus_button
+
+
+
+ def append(self, row):
+ self.insertAfter(len(self.pm_rows)-1, row)
+
+
+ def _getMinusAndPlusButtonsForRow(self, rowPosition):
+ """
+ Return as a tuple minus and plus buttons for the row specified by rowPosition
+ """
+ return (self.pm_rows[rowPosition][self.pm_noColumns], self.pm_rows[rowPosition][self.pm_noColumns+1])
+
+ def removeRow(self, rowPosition):
+ # remove widgets from table
+ for col in range(self.pm_noColumns + self.extraCols):
+ widget = self.pm_rows[rowPosition][col]
+ if widget:
+ self.remove(widget)
+ if self.pm_callbacks.has_key(widget):
+ widget.disconnect(self.pm_callbacks[widget])
+ del self.pm_callbacks[widget]
+
+
+ # reposition existing rows in gtk.Table
+ self._moveRows(-1, rowPosition + 1)
+ # remove row from list of rows
+ del self.pm_rows[rowPosition]
+
+ self._setMinusButtonSensitivity()
+ self.pm_noRows -= 1
+ self.resize(self.pm_noRows, self.pm_noColumns + self.extraCols)
+ self._printDebugInfo()
+
+
+ def _createCallback(self, widget, rowPosition, callbackType = None, callbackMethod=None):
+ if callbackType:
+ self.pm_callbacks[widget] = widget.connect(callbackType, callbackMethod, rowPosition)
+ else:
+ name = widget.get_name()
+ if name == 'GtkComboBox':
+ self.pm_callbacks[widget] = widget.connect("changed", self.on_combobox_changed, rowPosition)
+ elif name == 'GtkEntry':
+ self.pm_callbacks[widget] = widget.connect("changed", self.on_entry_changed, rowPosition)
+
+
+ def _moveRows(self, adjustment, startRow, endRow = -1):
+ """
+ Moves gtk.Table rows up or down according to adjustment (which MUST be -1 or 1).
+
+ Starts at row startRow and ends at row endRow. If endRow == -1, then goes to last row in table.
+ Readjusts callbacks.
+ """
+ if endRow == -1:
+ endRow = len(self.pm_rows)
+ for r in range(startRow, endRow):
+ if self.debug:
+ print "Row %s becomes row %s" % (self.pm_rows[r][self.pm_noColumns + 2].get_label(), r + adjustment)
+ self.pm_rows[r][self.pm_noColumns + 2].set_label(str(r + adjustment))
+
+ for col in range(self.pm_noColumns + self.extraCols):
+ widget = self.pm_rows[r][col]
+ if widget:
+ self.remove(widget)
+ widget.disconnect(self.pm_callbacks[widget])
+ self.attach(widget, col, col+1, r + adjustment, r + adjustment + 1)
+ if col == self.pm_noColumns:
+ self._createCallback(widget, r + adjustment, 'clicked', self.on_minus_button_clicked)
+ elif col == self.pm_noColumns + 1:
+ self._createCallback(widget, r + adjustment, 'clicked', self.on_plus_button_clicked)
+ else:
+ self._createCallback(widget, r + adjustment)
+
+
+ def _printDebugInfo(self):
+ if self.debug:
+ print "\nRows in internal list: %s\nTable rows: %s" % \
+ (len(self.pm_rows), self.pm_noRows)
+
+ if len(self.pm_rows) <> self.pm_noRows:
+ print "|\n\\\n --> Unequal no. of rows"
+
+
+
+ def attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions=gtk.EXPAND|gtk.FILL,
+ yoptions=gtk.SHRINK, xpadding=0, ypadding=0):
+ """
+ Override base class attach method, to allow automatic shrinking of minus and plus buttons
+ """
+ if left_attach >= self.pm_noColumns and left_attach <= self.pm_noColumns + 1:
+ # since we are adding plus or minus button, shrink the button
+ gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, gtk.SHRINK, gtk.SHRINK, xpadding, ypadding)
+ else:
+ gtk.Table.attach(self, child, left_attach, right_attach, top_attach, bottom_attach, xoptions, yoptions, xpadding, ypadding)
+
+
+ def insertAfter(self, rowPosition, row):
+ """
+ Inserts row into the table at row following rowPosition
+ """
+
+
+ #is table big enough?
+ self.checkTableRowsAndAdjust()
+
+ #move (reattach) other widgets & readjust connect
+ self._moveRows(1, rowPosition + 1)
+
+ # insert row
+ for col in range(self.pm_noColumns):
+ widget = row[col]
+ if widget:
+ self._createCallback(widget, rowPosition+1)
+ self.attach(widget, col, col+1, rowPosition+1, rowPosition+2)
+
+ minus_button, plus_button = self._createMinusPlusButtons(rowPosition+1)
+
+ row.append(minus_button)
+ row.append(plus_button)
+ self.attach(minus_button, self.pm_noColumns, self.pm_noColumns+1, rowPosition+1, rowPosition+2)
+ self.attach(plus_button, self.pm_noColumns+1, self.pm_noColumns+2, rowPosition+1, rowPosition+2)
+
+ if self.debug:
+ label = gtk.Label(str(rowPosition+1))
+ self.attach(label, self.pm_noColumns+2, self.pm_noColumns+3, rowPosition+1, rowPosition+2)
+ row.append(label)
+
+
+ for widget in row:
+ if widget:
+ widget.show()
+
+ #adjust internal reference table
+
+ self.pm_rows.insert(rowPosition + 1, row)
+
+ self._setMinusButtonSensitivity()
+
+ self._printDebugInfo()
+
+ def checkTableRowsAndAdjust(self, noRowsToAdd=1, adjustRows=True):
+ noRowsOk = True
+ if len(self.pm_rows) + noRowsToAdd > self.pm_noRows:
+ if adjustRows:
+ extraRowsToAdd = len(self.pm_rows) + noRowsToAdd - self.pm_noRows
+ self.pm_noRows += extraRowsToAdd
+ self.resize(self.pm_noRows, self.pm_noColumns + self.extraCols)
+ else:
+ noRowsOk = False
+ return noRowsOk
+
+ def getDefaultRow(self):
+ """
+ Returns a list of default widgets to insert as a row into the table.
+
+ Expected to be implemented in derived class.
+ """
+
+ return [None] * self.pm_noColumns
+
+ def on_combobox_changed(self, widget, rowPosition):
+ """
+ Callback for combobox that is expected to be implemented in derived class
+ """
+ pass
+
+ def on_entry_changed(self, widget, rowPosition):
+ """
+ Callback for entry that is expected to be implemented in derived class
+ """
+ pass
+
+ def _debugButtonPressed(self, buttonText, rowPosition):
+ if self.debug:
+ t = datetime.datetime.now().strftime("%H:%M:%S")
+ print "\n****\n%s\n\n%s clicked at %s" %(t, buttonText, rowPosition)
+
+ def on_minus_button_clicked(self, widget, rowPosition):
+ self._debugButtonPressed("Minus", rowPosition)
+ self.removeRow(rowPosition)
+ self.on_rowDeleted(rowPosition)
+
+ def on_plus_button_clicked(self, widget, rowPosition):
+ self._debugButtonPressed("Plus", rowPosition)
+ self.insertAfter(rowPosition, self.getDefaultRow())
+ self.on_rowAdded(rowPosition)
+
+ def on_rowAdded(self, rowPosition):
+ """
+ Expected to be implemented in derived class
+ """
+ pass
+
+ def on_rowDeleted(self, rowPosition):
+ """
+ Expected to be implemented in derived class
+ """
+ pass
+
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..2af92b4
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: latin1 -*-
+
+from distutils.core import setup
+from distutils.command.install_data import install_data
+from distutils.dep_util import newer
+from distutils.log import info
+
+from rapid.config import version
+import glob
+import os
+
+name = 'rapid-photo-downloader'
+
+class InstallData(install_data):
+ """ This class is largely copied from setup.py in Terminator 0.8.1 by Chris Jones <cmsj@tenshu.net>"""
+ def run (self):
+ self.data_files.extend (self._compile_po_files ())
+ install_data.run (self)
+
+ def _compile_po_files (self):
+ data_files = []
+
+ PO_DIR = 'po'
+ for po in glob.glob (os.path.join (PO_DIR,'*.po')):
+ lang = os.path.basename(po[:-3])
+ mo = os.path.join('build', 'mo', lang, '%s.mo' % name)
+
+ directory = os.path.dirname(mo)
+ if not os.path.exists(directory):
+ info('creating %s' % directory)
+ os.makedirs(directory)
+
+ if newer(po, mo):
+ # True if mo doesn't exist
+ cmd = 'msgfmt -o %s %s' % (mo, po)
+ info('compiling %s -> %s' % (po, mo))
+ if os.system(cmd) != 0:
+ raise SystemExit('Error while running msgfmt')
+
+ dest = os.path.dirname(os.path.join('share', 'locale', lang, 'LC_MESSAGES', '%s.mo' % name))
+ data_files.append((dest, [mo]))
+
+ return data_files
+
+package_data={'rapid': ['glade3/rapid.glade', 'glade3/rapid-photo-downloader-about.png', 'glade3/image-missing.svg']}
+
+setup(name=name,
+ version=version,
+ description='Rapid Photo Downloader for Linux',
+ license='GPL',
+ author='Damon Lynch',
+ author_email='damonlynch@gmail.com',
+ maintainer='Damon Lynch',
+ url='http://www.damonlynch.net/rapid',
+ long_description=
+"""Rapid Photo Downloader is written by a photographer for
+professional and amateur photographers. It can download photos
+from multiple cameras, memory cards and Portable Storage Devices
+simultaneously. It provides many options for subfolder creation,
+image renaming and backup.""",
+ packages = ['rapid'],
+ package_data=package_data,
+ scripts=['rapid-photo-downloader'],
+ platforms=['linux'],
+ data_files=[
+ ('share/applications', ['data/rapid-photo-downloader.desktop']),
+ ('share/pixmaps', ['data/icons/48x48/apps/rapid-photo-downloader.png', 'data/icons/rapid-photo-downloader.xpm']),
+ ('share/icons/hicolor/scalable/apps', glob.glob('data/icons/scalable/apps/*.svg')),
+ ('share/icons/hicolor/16x16/apps', glob.glob('data/icons/16x16/apps/*.png')),
+ ('share/icons/hicolor/22x22/apps', glob.glob('data/icons/22x22/apps/*.png')),
+ ('share/icons/hicolor/24x24/apps', glob.glob('data/icons/24x24/apps/*.png')),
+ ('share/icons/hicolor/48x48/apps', glob.glob('data/icons/48x48/apps/*.png')),
+ ],
+ cmdclass={'install_data': InstallData}
+)