diff options
Diffstat (limited to 'interfaces')
53 files changed, 6146 insertions, 0 deletions
diff --git a/interfaces/gui/icons/abort.png b/interfaces/gui/icons/abort.png Binary files differnew file mode 100644 index 000000000..66170aae7 --- /dev/null +++ b/interfaces/gui/icons/abort.png diff --git a/interfaces/gui/icons/clipboard.png b/interfaces/gui/icons/clipboard.png Binary files differnew file mode 100644 index 000000000..9ba608eba --- /dev/null +++ b/interfaces/gui/icons/clipboard.png diff --git a/interfaces/gui/icons/close.png b/interfaces/gui/icons/close.png Binary files differnew file mode 100644 index 000000000..66170aae7 --- /dev/null +++ b/interfaces/gui/icons/close.png diff --git a/interfaces/gui/icons/edit_small.png b/interfaces/gui/icons/edit_small.png Binary files differnew file mode 100644 index 000000000..eb76e21b4 --- /dev/null +++ b/interfaces/gui/icons/edit_small.png diff --git a/interfaces/gui/icons/logo.png b/interfaces/gui/icons/logo.png Binary files differnew file mode 100644 index 000000000..72a95b740 --- /dev/null +++ b/interfaces/gui/icons/logo.png diff --git a/interfaces/gui/icons/pull_small.png b/interfaces/gui/icons/pull_small.png Binary files differnew file mode 100644 index 000000000..432ad321f --- /dev/null +++ b/interfaces/gui/icons/pull_small.png diff --git a/interfaces/gui/icons/push_small.png b/interfaces/gui/icons/push_small.png Binary files differnew file mode 100644 index 000000000..701fc69e3 --- /dev/null +++ b/interfaces/gui/icons/push_small.png diff --git a/interfaces/gui/icons/refresh_small.png b/interfaces/gui/icons/refresh_small.png Binary files differnew file mode 100644 index 000000000..1ffd18d97 --- /dev/null +++ b/interfaces/gui/icons/refresh_small.png diff --git a/interfaces/gui/icons/remove_small.png b/interfaces/gui/icons/remove_small.png Binary files differnew file mode 100644 index 000000000..bf99763e8 --- /dev/null +++ b/interfaces/gui/icons/remove_small.png diff --git a/interfaces/gui/icons/toolbar_add.png b/interfaces/gui/icons/toolbar_add.png Binary files differnew file mode 100644 index 000000000..17003e9f0 --- /dev/null +++ b/interfaces/gui/icons/toolbar_add.png diff --git a/interfaces/gui/icons/toolbar_pause.png b/interfaces/gui/icons/toolbar_pause.png Binary files differnew file mode 100644 index 000000000..b7a727b71 --- /dev/null +++ b/interfaces/gui/icons/toolbar_pause.png diff --git a/interfaces/gui/icons/toolbar_remove.png b/interfaces/gui/icons/toolbar_remove.png Binary files differnew file mode 100644 index 000000000..1e9c00e16 --- /dev/null +++ b/interfaces/gui/icons/toolbar_remove.png diff --git a/interfaces/gui/icons/toolbar_start.png b/interfaces/gui/icons/toolbar_start.png Binary files differnew file mode 100644 index 000000000..1123266e6 --- /dev/null +++ b/interfaces/gui/icons/toolbar_start.png diff --git a/interfaces/gui/icons/toolbar_stop.png b/interfaces/gui/icons/toolbar_stop.png Binary files differnew file mode 100644 index 000000000..b388e3d72 --- /dev/null +++ b/interfaces/gui/icons/toolbar_stop.png diff --git a/interfaces/gui/locale/de/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/de/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..7fca76598 --- /dev/null +++ b/interfaces/gui/locale/de/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/de/gui.po b/interfaces/gui/locale/de/gui.po new file mode 100644 index 000000000..63cd861b5 --- /dev/null +++ b/interfaces/gui/locale/de/gui.po @@ -0,0 +1,256 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\n" +"PO-Revision-Date: 2010-02-04 22:56+0200\n" +"Last-Translator: Marius <mkaay@mkaay.de>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Pootle 2.0.0\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "Captcha" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "OK" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "Abbrechen" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "Neu" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "Bearbeiten" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "Entfernen" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "Verbinden" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "%s (Standard)" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "Name:" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "Host:" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "SSL:" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "Lokal:" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "Benutzer:" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "Port:" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "Speichern" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "pyLoad Client" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "Status: nicht verbunden" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "Datei" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "Verbindungen" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "Beenden" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "Verbindungen verwalten" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "Warteschlange" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "Linksammler" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "Einstellungen" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "Log" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "Toolbar" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "pause/fortsetzen" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "Stop" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "Hinzufügen" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "Zwischenablage überwachen" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "Paket" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "Links" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "Container" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "Pakete" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "Verschiebe ausgewählte Pakete in die Warteschlange" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "Neustarten" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "in Linksammler verschieben" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "in Warteschlange verschieben" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "Name bearbeiten" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "Alle Container Arten (%s)" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "DLC (%s)" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "CCF (%s)" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "RSDF (%s)" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "Text Dateien (%s)" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "Container öffnen" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "Einzelne Links" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "Passwort:" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "Neues Paket" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "Name" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "Links in diesem Paket" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "Erstellen" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "Plugin" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "Fortschritt" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "Status" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "Pausiert" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "Läuft" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "Status: %(status)s | Geschwindigkeit: %(speed)s kb/s" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "Update verfügbar" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "Unbenannt" diff --git a/interfaces/gui/locale/en/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/en/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/en/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/en/gui.po b/interfaces/gui/locale/en/gui.po new file mode 100644 index 000000000..0cc6cf7ec --- /dev/null +++ b/interfaces/gui/locale/en/gui.po @@ -0,0 +1,256 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\n" +"PO-Revision-Date: 2010-02-04 21:28+0200\n" +"Last-Translator: Marius <mkaay@mkaay.de>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: en\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Pootle 2.0.0\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "Captcha" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "OK" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "Cancel" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "New" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "Edit" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "Remove" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "Connect" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "%s (Default)" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "Name:" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "Host:" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "SSL:" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "Local:" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "User:" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "Port:" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "Save" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "pyLoad Client" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "Status: Not Connected" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "File" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "Connections" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "Exit" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "Connection manager" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "Queue" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "Collector" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "Settings" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "Log" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "Main Toolbar" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "Toggle Pause/Resume" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "Stop" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "Add" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "Check Clipboard" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "Package" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "Links" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "Container" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "Packages" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "Push selected packages to queue" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "Restart" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "Pull out" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "Push to queue" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "Edit Name" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "All Container Types (%s)" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "DLC (%s)" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "CCF (%s)" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "RSDF (%s)" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "Text Files (%s)" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "Open container" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "Single Links" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "Password:" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "New Package" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "Name" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "Links in this Package" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "Create" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "Plugin" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "Progress" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "Status" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "Paused" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "Running" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "Status: %(status)s | Speed: %(speed)s kb/s" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "Update Available" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "Unnamed" diff --git a/interfaces/gui/locale/es/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/es/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/es/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/es/gui.po b/interfaces/gui/locale/es/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/es/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/locale/fi/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/fi/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/fi/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/fi/gui.po b/interfaces/gui/locale/fi/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/fi/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/locale/fr/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/fr/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/fr/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/fr/gui.po b/interfaces/gui/locale/fr/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/fr/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/locale/gui.pot b/interfaces/gui/locale/gui.pot new file mode 100644 index 000000000..aae5349f0 --- /dev/null +++ b/interfaces/gui/locale/gui.pot @@ -0,0 +1,254 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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: ENCODING\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" + diff --git a/interfaces/gui/locale/it/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/it/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/it/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/it/gui.po b/interfaces/gui/locale/it/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/it/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/locale/nl/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/nl/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..94df0f64b --- /dev/null +++ b/interfaces/gui/locale/nl/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/nl/gui.po b/interfaces/gui/locale/nl/gui.po new file mode 100644 index 000000000..15562c9be --- /dev/null +++ b/interfaces/gui/locale/nl/gui.po @@ -0,0 +1,257 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\n" +"PO-Revision-Date: 2010-02-16 14:32+0200\n" +"Last-Translator: <laurenshoogstraten@gmail.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Pootle 2.0.0\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "Captcha" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "OK" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "Annuleer" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "Nieuw" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "Wijzigen" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "Verwijder" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "Verbinden" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "%s (Standaard)" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "Naam:" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "Host:" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "SSL:" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "Lokaal:" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "Gebruiker:" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "Port:" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "Opslaan" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "pyLoad cliënt" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "Status: Niet verbonden" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "Bestand" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "Verbindingen" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "Afsluiten" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "Verbindingen beheer" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "Wachtrij" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "Verzamelaar" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "Instellingen" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "Logboek" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "Hoofd Toolbar" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "Pauze/Herstarten" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "Stop" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "Toevoegen" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "Check Klembord" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "Pakket" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "Links" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "Container" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "Pakketen" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "Verplaats de geselecteerde pakketen naar de wacht rij" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "Herstart" + +# Don't know in wich context this is. +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "Pull out" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "Verplaats naar wacht rij" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "Wijzig Naam" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "Alle Containers types (%s)" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "DLC (%s)" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "CCF (%s)" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "RSDF (%s)" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "Tekst Bestanden (%s)" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "Open container" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "Enkele Links" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "Wachtwoord:" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "Nieuw Pakket" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "Naam" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "Links in dit pakket" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "Creëer" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "Plugin" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "Vooruitgang" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "Status" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "Gepauzeerd" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "Gestart" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "Status: %(status)s | Snelheid: %(speed)s kb/s" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "Update Beschikbaar" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "Naamloos" diff --git a/interfaces/gui/locale/pl/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/pl/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..7d1745301 --- /dev/null +++ b/interfaces/gui/locale/pl/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/pl/gui.po b/interfaces/gui/locale/pl/gui.po new file mode 100644 index 000000000..a4ef49e11 --- /dev/null +++ b/interfaces/gui/locale/pl/gui.po @@ -0,0 +1,257 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\n" +"PO-Revision-Date: 2010-02-05 01:18+0200\n" +"Last-Translator: <martii@interia.pl>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Pootle 2.0.0\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "Token" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "OK" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "Anuluj" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "Nowy" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "Edytuj" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "Usuń" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "Połącz" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "%s (domyślnie)" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "Nazwa:" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "Host:" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "SSL:" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "Lokalny:" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "Użytkownik:" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "Port:" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "Zapisz" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "Klient pyLoad" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "Status: nie połączony" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "Plik" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "Połączenia" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "Wyjście" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "Zarządzanie połączeniami" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "Kolejka" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "Kolektor" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "Ustawienia" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "Log" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "Główny pasek" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "Wstrzymaj/Wznów" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "Zatrzymaj" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "Dodaj" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "Sprawdź schowek" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "Paczka" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "Linki" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "Kontener" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "Paczki" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "Wyślij wybraną paczkę do kolejki" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "Restartuj" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "Wycofaj" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "Wyślij do kolejki" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "Edytuj nazwę" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "Wszystkie rodzaje kontenerów (%s)" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "DLC (%s)" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "CCF (%s)" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "RSDF (%s)" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "Pliki tekstowe (%s)" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "Otwórz kontener" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "Pojedyńcze linki" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "Hasło:" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "Nowa paczka" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "Nazwa" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "Linki na tej stronie" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "Utwórz" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "Wtyczka" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "Postęp" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "Stan" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "Wstrzymany" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "Uruchomiony" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "Stan: %(status)s | Prędkość: %(speed)s kb/s" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "Jest dostępna aktualizacja" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "Bez nazwy" diff --git a/interfaces/gui/locale/ro/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/ro/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/ro/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/ro/gui.po b/interfaces/gui/locale/ro/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/ro/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/locale/ru/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/ru/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/ru/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/ru/gui.po b/interfaces/gui/locale/ru/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/ru/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/locale/tr/LC_MESSAGES/pyLoadGui.mo b/interfaces/gui/locale/tr/LC_MESSAGES/pyLoadGui.mo Binary files differnew file mode 100644 index 000000000..1ae24953f --- /dev/null +++ b/interfaces/gui/locale/tr/LC_MESSAGES/pyLoadGui.mo diff --git a/interfaces/gui/locale/tr/gui.po b/interfaces/gui/locale/tr/gui.po new file mode 100644 index 000000000..b8bd3b9ee --- /dev/null +++ b/interfaces/gui/locale/tr/gui.po @@ -0,0 +1,255 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ORGANIZATION +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-02-03 15:21+CET\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=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Translate Toolkit 1.5.1\n" +"Generated-By: pygettext.py 1.5\n" + +#: ./module/gui/CaptchaDock.py:25 +msgid "Captcha" +msgstr "" + +#: ./module/gui/CaptchaDock.py:56 ./module/gui/PWInputWindow.py:28 +msgid "OK" +msgstr "" + +#: ./module/gui/CaptchaDock.py:57 ./module/gui/ConnectionManager.py:154 +#: ./module/gui/PWInputWindow.py:29 +msgid "Cancel" +msgstr "" + +#: ./module/gui/ConnectionManager.py:33 +msgid "New" +msgstr "" + +#: ./module/gui/ConnectionManager.py:34 +msgid "Edit" +msgstr "" + +#: ./module/gui/ConnectionManager.py:35 ./module/gui/MainWindow.py:191 +#: ./module/gui/MainWindow.py:205 +msgid "Remove" +msgstr "" + +#: ./module/gui/ConnectionManager.py:36 +msgid "Connect" +msgstr "" + +#: ./module/gui/ConnectionManager.py:76 +msgid "%s (Default)" +msgstr "" + +#: ./module/gui/ConnectionManager.py:138 +msgid "Name:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:139 +msgid "Host:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:140 +msgid "SSL:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:141 +msgid "Local:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:142 +msgid "User:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:143 +msgid "Port:" +msgstr "" + +#: ./module/gui/ConnectionManager.py:153 +msgid "Save" +msgstr "" + +#: ./module/gui/MainWindow.py:33 +msgid "pyLoad Client" +msgstr "" + +#: ./module/gui/MainWindow.py:60 +msgid "Status: Not Connected" +msgstr "" + +#: ./module/gui/MainWindow.py:65 +msgid "File" +msgstr "" + +#: ./module/gui/MainWindow.py:66 +msgid "Connections" +msgstr "" + +#: ./module/gui/MainWindow.py:70 +msgid "Exit" +msgstr "" + +#: ./module/gui/MainWindow.py:71 +msgid "Connection manager" +msgstr "" + +#: ./module/gui/MainWindow.py:88 +msgid "Queue" +msgstr "" + +#: ./module/gui/MainWindow.py:89 +msgid "Collector" +msgstr "" + +#: ./module/gui/MainWindow.py:90 +msgid "Settings" +msgstr "" + +#: ./module/gui/MainWindow.py:91 +msgid "Log" +msgstr "" + +#: ./module/gui/MainWindow.py:117 +msgid "Main Toolbar" +msgstr "" + +#: ./module/gui/MainWindow.py:120 +msgid "Toggle Pause/Resume" +msgstr "" + +#: ./module/gui/MainWindow.py:126 +msgid "Stop" +msgstr "" + +#: ./module/gui/MainWindow.py:128 +msgid "Add" +msgstr "" + +#: ./module/gui/MainWindow.py:130 +msgid "Check Clipboard" +msgstr "" + +#: ./module/gui/MainWindow.py:137 +msgid "Package" +msgstr "" + +#: ./module/gui/MainWindow.py:138 +msgid "Links" +msgstr "" + +#: ./module/gui/MainWindow.py:139 +msgid "Container" +msgstr "" + +#: ./module/gui/MainWindow.py:156 +msgid "Packages" +msgstr "" + +#: ./module/gui/MainWindow.py:158 +msgid "Push selected packages to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:192 +msgid "Restart" +msgstr "" + +#: ./module/gui/MainWindow.py:193 +msgid "Pull out" +msgstr "" + +#: ./module/gui/MainWindow.py:206 +msgid "Push to queue" +msgstr "" + +#: ./module/gui/MainWindow.py:207 +msgid "Edit Name" +msgstr "" + +#: ./module/gui/MainWindow.py:277 +msgid "All Container Types (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:278 +msgid "DLC (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:279 +msgid "CCF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:280 +msgid "RSDF (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:281 +msgid "Text Files (%s)" +msgstr "" + +#: ./module/gui/MainWindow.py:283 +msgid "Open container" +msgstr "" + +#: ./module/gui/MainWindow.py:306 +msgid "Single Links" +msgstr "" + +#: ./module/gui/PWInputWindow.py:27 +msgid "Password:" +msgstr "" + +#: ./module/gui/PackageDock.py:24 +msgid "New Package" +msgstr "" + +#: ./module/gui/PackageDock.py:50 ./pyLoadGui.py:236 +msgid "Name" +msgstr "" + +#: ./module/gui/PackageDock.py:53 +msgid "Links in this Package" +msgstr "" + +#: ./module/gui/PackageDock.py:68 +msgid "Create" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Plugin" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Progress" +msgstr "" + +#: ./pyLoadGui.py:236 +msgid "Status" +msgstr "" + +#: ./pyLoadGui.py:252 +msgid "Paused" +msgstr "" + +#: ./pyLoadGui.py:254 +msgid "Running" +msgstr "" + +#: ./pyLoadGui.py:256 +msgid "Status: %(status)s | Speed: %(speed)s kb/s" +msgstr "" + +#: ./pyLoadGui.py:281 +msgid "Update Available" +msgstr "" + +#: ./pyLoadGui.py:305 +msgid "Unnamed" +msgstr "" diff --git a/interfaces/gui/module/__init__.py b/interfaces/gui/module/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/interfaces/gui/module/__init__.py diff --git a/interfaces/gui/module/config/gui_default.xml b/interfaces/gui/module/config/gui_default.xml new file mode 100644 index 000000000..1faed776f --- /dev/null +++ b/interfaces/gui/module/config/gui_default.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" ?> +<root> + <connections> + <connection default="True" type="local" id="33965310e19b4a869112c43b39a16440"> + <name>Local</name> + </connection> + </connections> + <mainWindow> + <state></state> + <geometry></geometry> + </mainWindow> + <language>en</language> +</root> diff --git a/interfaces/gui/module/gui/Accounts.py b/interfaces/gui/module/gui/Accounts.py new file mode 100644 index 000000000..f47928c1a --- /dev/null +++ b/interfaces/gui/module/gui/Accounts.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from time import strftime, gmtime + +class AccountModel(QAbstractItemModel): + def __init__(self, view, connector): + QAbstractItemModel.__init__(self) + self.connector = connector + self.view = view + self._data = [] + self.cols = 4 + self.mutex = QMutex() + + def reloadData(self): + data = self.connector.proxy.get_accounts() + self.beginRemoveRows(QModelIndex(), 0, len(self._data)) + self._data = [] + self.endRemoveRows() + accounts = [] + for li in data.values(): + accounts += li + self.beginInsertRows(QModelIndex(), 0, len(accounts)) + self._data = accounts + self.endInsertRows() + + def toData(self, index): + return index.internalPointer() + + def data(self, index, role=Qt.DisplayRole): + if not index.isValid(): + return QVariant() + if role == Qt.DisplayRole: + if index.column() == 0: + return QVariant(self.toData(index)["type"]) + elif index.column() == 1: + return QVariant(self.toData(index)["login"]) + elif index.column() == 2: + if not self.toData(index)["validuntil"]: + return QVariant(_("n/a")) + until = int(self.toData(index)["validuntil"]) + if until > 0: + fmtime = strftime(_("%a, %d %b %Y %H:%M"), gmtime(until)) + return QVariant(fmtime) + else: + return QVariant(_("unlimited")) + elif index.column() == 3: + return QVariant(self.toData(index)["trafficleft"]) + #elif role == Qt.EditRole: + # if index.column() == 0: + # return QVariant(index.internalPointer().data["name"]) + return QVariant() + + def index(self, row, column, parent=QModelIndex()): + if parent == QModelIndex() and len(self._data) > row: + pointer = self._data[row] + index = self.createIndex(row, column, pointer) + elif parent.isValid(): + pointer = parent.internalPointer().children[row] + index = self.createIndex(row, column, pointer) + else: + index = QModelIndex() + return index + + def parent(self, index): + return QModelIndex() + + def rowCount(self, parent=QModelIndex()): + if parent == QModelIndex(): + return len(self._data) + return 0 + + def columnCount(self, parent=QModelIndex()): + return self.cols + + def hasChildren(self, parent=QModelIndex()): + return False + + def canFetchMore(self, parent): + return False + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if orientation == Qt.Horizontal and role == Qt.DisplayRole: + if section == 0: + return QVariant(_("Type")) + elif section == 1: + return QVariant(_("Login")) + elif section == 2: + return QVariant(_("Valid until")) + elif section == 3: + return QVariant(_("Traffic left")) + return QVariant() + + def flags(self, index): + return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled + + #def setData(self, index, value, role=Qt.EditRole): + # if index.column() == 0 and self.parent(index) == QModelIndex() and role == Qt.EditRole: + # self.connector.setPackageName(index.internalPointer().id, str(value.toString())) + # return True + +class AccountView(QTreeView): + def __init__(self, connector): + QTreeView.__init__(self) + self.setModel(AccountModel(self, connector)) + + self.setColumnWidth(0, 150) + self.setColumnWidth(1, 150) + self.setColumnWidth(2, 150) + self.setColumnWidth(3, 150) + + self.setEditTriggers(QAbstractItemView.NoEditTriggers) + + self.delegate = AccountDelegate(self, self.model()) + self.setItemDelegateForColumn(3, self.delegate) + +class AccountDelegate(QItemDelegate): + def __init__(self, parent, model): + QItemDelegate.__init__(self, parent) + self.model = model + + def paint(self, painter, option, index): + if not index.isValid(): + return + if index.column() == 3: + data = self.model.toData(index) + opts = QStyleOptionProgressBarV2() + opts.minimum = 0 + if data["trafficleft"]: + if data["trafficleft"] == -1: + opts.maximum = opts.progress = 1 + else: + opts.maximum = opts.progress = data["trafficleft"] + if data["maxtraffic"]: + opts.maximum = data["maxtraffic"] + + opts.rect = option.rect + opts.rect.setRight(option.rect.right()-1) + opts.rect.setHeight(option.rect.height()-1) + opts.textVisible = True + opts.textAlignment = Qt.AlignCenter + if data["trafficleft"] and data["trafficleft"] == -1: + opts.text = QString(_("unlimited")) + else: + opts.text = QString.number(round(float(opts.progress)/1024/1024, 2)) + " GB" + QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) + return + QItemDelegate.paint(self, painter, option, index) + diff --git a/interfaces/gui/module/gui/CaptchaDock.py b/interfaces/gui/module/gui/CaptchaDock.py new file mode 100644 index 000000000..4f3c9efd0 --- /dev/null +++ b/interfaces/gui/module/gui/CaptchaDock.py @@ -0,0 +1,85 @@ +# -*- coding: utf-8 -*- + +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +class CaptchaDock(QDockWidget): + def __init__(self): + QDockWidget.__init__(self, _("Captcha")) + self.setObjectName("Captcha Dock") + self.widget = CaptchaDockWidget(self) + self.setWidget(self.widget) + self.setAllowedAreas(Qt.BottomDockWidgetArea) + self.setFeatures(QDockWidget.NoDockWidgetFeatures) + self.hide() + self.processing = False + self.currentID = None + self.connect(self, SIGNAL("setTask"), self.setTask) + + def isFree(self): + return not self.processing + + def setTask(self, tid, img, imgType): + self.processing = True + data = QByteArray(img) + self.currentID = tid + self.widget.emit(SIGNAL("setImage"), data) + self.widget.input.setText("") + self.show() + +class CaptchaDockWidget(QWidget): + def __init__(self, dock): + QWidget.__init__(self) + self.dock = dock + self.setLayout(QHBoxLayout()) + layout = self.layout() + + imgLabel = QLabel() + captchaInput = QLineEdit() + okayButton = QPushButton(_("OK")) + cancelButton = QPushButton(_("Cancel")) + + layout.addStretch() + layout.addWidget(imgLabel) + layout.addWidget(captchaInput) + layout.addWidget(okayButton) + layout.addWidget(cancelButton) + layout.addStretch() + + self.input = captchaInput + + self.connect(okayButton, SIGNAL("clicked()"), self.slotSubmit) + self.connect(captchaInput, SIGNAL("returnPressed()"), self.slotSubmit) + self.connect(self, SIGNAL("setImage"), self.setImg) + self.connect(self, SIGNAL("setPixmap(const QPixmap &)"), imgLabel, SLOT("setPixmap(const QPixmap &)")) + + def setImg(self, data): + pixmap = QPixmap() + pixmap.loadFromData(data) + self.emit(SIGNAL("setPixmap(const QPixmap &)"), pixmap) + + def slotSubmit(self): + text = self.input.text() + tid = self.dock.currentID + self.dock.currentID = None + self.dock.emit(SIGNAL("done"), tid, str(text)) + self.dock.hide() + self.dock.processing = False + diff --git a/interfaces/gui/module/gui/Collector.py b/interfaces/gui/module/gui/Collector.py new file mode 100644 index 000000000..f7bfcbebf --- /dev/null +++ b/interfaces/gui/module/gui/Collector.py @@ -0,0 +1,289 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +statusMap = { + "finished": 0, + "offline": 1, + "online": 2, + "queued": 3, + "checking": 4, + "waiting": 5, + "reconnected": 6, + "starting": 7, + "failed": 8, + "aborted": 9, + "decrypting": 10, + "custom": 11, + "downloading": 12, + "processing": 13 +} +statusMapReverse = dict((v,k) for k, v in statusMap.iteritems()) + +class CollectorModel(QAbstractItemModel): + def __init__(self, view, connector): + QAbstractItemModel.__init__(self) + self.connector = connector + self.view = view + self._data = [] + self.cols = 3 + self.interval = 1 + self.mutex = QMutex() + + def addEvent(self, event): + locker = QMutexLocker(self.mutex) + if event[0] == "reload": + self.fullReload() + elif event[0] == "remove": + self.removeEvent(event) + elif event[0] == "insert": + self.insertEvent(event) + elif event[0] == "update": + self.updateEvent(event) + + def fullReload(self): + self._data = [] + packs = self.connector.getPackageCollector() + self.beginInsertRows(QModelIndex(), 0, len(packs)) + for pid, data in packs.items(): + package = Package(pid, data) + self._data.append(package) + self._data = sorted(self._data, key=lambda p: p.data["order"]) + self.endInsertRows() + + def removeEvent(self, event): + if event[2] == "file": + for p, package in enumerate(self._data): + for k, child in enumerate(package.children): + if child.id == int(event[3]): + self.beginRemoveRows(self.index(p, 0), k, k) + del package.children[k] + self.endRemoveRows() + break + else: + for k, package in enumerate(self._data): + if package.id == int(event[3]): + self.beginRemoveRows(QModelIndex(), k, k) + del self._data[k] + self.endRemoveRows() + break + + def insertEvent(self, event): + if event[2] == "file": + info = self.connector.proxy.get_file_data(int(event[3])) + fid = info.keys()[0] + info = info.values()[0] + + for k, package in enumerate(self._data): + if package.id == int(info["package"]): + if package.getChild(fid): + del event[4] + self.updateEvent(event) + break + self.beginInsertRows(self.index(k, 0), info["order"], info["order"]) + package.addChild(fid, info, info["order"]) + self.endInsertRows() + break + else: + data = self.connector.proxy.get_package_data(event[3]) + package = Package(event[3], data) + self.beginInsertRows(QModelIndex(), data["order"], data["order"]) + self._data.insert(data["order"], package) + self.endInsertRows() + + def updateEvent(self, event): + if event[2] == "file": + info = self.connector.proxy.get_file_data(int(event[3])) + if not info: + return + fid = info.keys()[0] + info = info.values()[0] + for p, package in enumerate(self._data): + if package.id == int(info["package"]): + for k, child in enumerate(package.children): + if child.id == int(event[3]): + child.data = info + child.data["downloading"] = None + self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(k, 0, self.index(p, 0)), self.index(k, self.cols, self.index(p, self.cols))) + break + else: + data = self.connector.proxy.get_package_data(int(event[3])) + if not data: + return + pid = event[3] + del data["links"] + for p, package in enumerate(self._data): + if package.id == int(pid): + package.data = data + self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(p, 0), self.index(p, self.cols)) + break + + def data(self, index, role=Qt.DisplayRole): + if not index.isValid(): + return QVariant() + if role == Qt.DisplayRole: + if index.column() == 0: + return QVariant(index.internalPointer().data["name"]) + elif index.column() == 2: + item = index.internalPointer() + status = 0 + if isinstance(item, Package): + for child in item.children: + if child.data["status"] > status: + status = child.data["status"] + else: + status = item.data["status"] + return QVariant(statusMapReverse[status]) + elif index.column() == 1: + item = index.internalPointer() + plugins = [] + if isinstance(item, Package): + for child in item.children: + if not child.data["plugin"] in plugins: + plugins.append(child.data["plugin"]) + else: + plugins.append(item.data["plugin"]) + return QVariant(", ".join(plugins)) + elif role == Qt.EditRole: + if index.column() == 0: + return QVariant(index.internalPointer().data["name"]) + return QVariant() + + def index(self, row, column, parent=QModelIndex()): + if parent == QModelIndex() and len(self._data) > row: + pointer = self._data[row] + index = self.createIndex(row, column, pointer) + elif parent.isValid(): + pointer = parent.internalPointer().children[row] + index = self.createIndex(row, column, pointer) + else: + index = QModelIndex() + return index + + def parent(self, index): + if index == QModelIndex(): + return QModelIndex() + if index.isValid(): + link = index.internalPointer() + if isinstance(link, Link): + for k, pack in enumerate(self._data): + if pack == link.package: + return self.createIndex(k, 0, link.package) + return QModelIndex() + + def rowCount(self, parent=QModelIndex()): + if parent == QModelIndex(): + #return package count + return len(self._data) + else: + if parent.isValid(): + #index is valid + pack = parent.internalPointer() + if isinstance(pack, Package): + #index points to a package + #return len of children + return len(pack.children) + else: + #index is invalid + return False + #files have no children + return 0 + + def columnCount(self, parent=QModelIndex()): + return self.cols + + def hasChildren(self, parent=QModelIndex()): + if not parent.isValid(): + return True + return (self.rowCount(parent) > 0) + + def canFetchMore(self, parent): + return False + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if orientation == Qt.Horizontal and role == Qt.DisplayRole: + if section == 0: + return QVariant(_("Name")) + elif section == 2: + return QVariant(_("Status")) + elif section == 1: + return QVariant(_("Plugin")) + return QVariant() + + def flags(self, index): + if index.column() == 0 and self.parent(index) == QModelIndex(): + return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled + return Qt.ItemIsSelectable | Qt.ItemIsEnabled + + def setData(self, index, value, role=Qt.EditRole): + if index.column() == 0 and self.parent(index) == QModelIndex() and role == Qt.EditRole: + self.connector.setPackageName(index.internalPointer().id, str(value.toString())) + return True + +class Package(object): + def __init__(self, pid, data): + self.id = int(pid) + self.children = [] + for fid, fdata in data["links"].items(): + self.addChild(int(fid), fdata) + del data["links"] + self.data = data + + def addChild(self, fid, data, pos=None): + if pos is None: + self.children.insert(data["order"], Link(fid, data, self)) + else: + self.children.insert(pos, Link(fid, data, self)) + self.children = sorted(self.children, key=lambda l: l.data["order"]) + + def getChild(self, fid): + for child in self.children: + if child.id == int(fid): + return child + return None + + def getChildKey(self, fid): + for k, child in enumerate(self.children): + if child.id == int(fid): + return k + return None + + def removeChild(self, fid): + for k, child in enumerate(self.children): + if child.id == int(fid): + del self.children[k] + +class Link(object): + def __init__(self, fid, data, pack): + self.data = data + self.data["downloading"] = None + self.id = int(fid) + self.package = pack + +class CollectorView(QTreeView): + def __init__(self, connector): + QTreeView.__init__(self) + self.setModel(CollectorModel(self, connector)) + self.setColumnWidth(0, 500) + self.setColumnWidth(1, 100) + self.setColumnWidth(2, 200) + + self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed) + diff --git a/interfaces/gui/module/gui/ConnectionManager.py b/interfaces/gui/module/gui/ConnectionManager.py new file mode 100644 index 000000000..0bdeae282 --- /dev/null +++ b/interfaces/gui/module/gui/ConnectionManager.py @@ -0,0 +1,261 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from uuid import uuid4 as uuid + +class ConnectionManager(QWidget): + def __init__(self): + QWidget.__init__(self) + + mainLayout = QHBoxLayout() + buttonLayout = QVBoxLayout() + + connList = QListWidget() + + new = QPushButton(_("New")) + edit = QPushButton(_("Edit")) + remove = QPushButton(_("Remove")) + connect = QPushButton(_("Connect")) + + mainLayout.addWidget(connList) + mainLayout.addLayout(buttonLayout) + + buttonLayout.addWidget(new) + buttonLayout.addWidget(edit) + buttonLayout.addWidget(remove) + buttonLayout.addStretch() + buttonLayout.addWidget(connect) + + self.setLayout(mainLayout) + + self.new = new + self.connectb = connect + self.remove = remove + self.editb = edit + self.connList = connList + self.edit = self.EditWindow() + self.connectSignals() + + self.defaultStates = {} + + def connectSignals(self): + self.connect(self, SIGNAL("setConnections"), self.setConnections) + self.connect(self.new, SIGNAL("clicked()"), self.slotNew) + self.connect(self.editb, SIGNAL("clicked()"), self.slotEdit) + self.connect(self.remove, SIGNAL("clicked()"), self.slotRemove) + self.connect(self.connectb, SIGNAL("clicked()"), self.slotConnect) + self.connect(self.edit, SIGNAL("save"), self.slotSave) + self.connect(self.connList, SIGNAL("itemDoubleClicked(QListWidgetItem *)"), self.slotItemDoubleClicked) + + def setConnections(self, connections): + self.connList.clear() + for conn in connections: + item = QListWidgetItem() + item.setData(Qt.DisplayRole, QVariant(conn["name"])) + item.setData(Qt.UserRole, QVariant(conn)) + self.connList.addItem(item) + if conn["default"]: + item.setData(Qt.DisplayRole, QVariant(_("%s (Default)") % conn["name"])) + self.connList.setCurrentItem(item) + + def slotNew(self): + data = {"id":uuid().hex, "type":"remote", "default":False, "name":"", "host":"", "ssl":False, "port":"7227", "user":"admin", "password":""} + self.edit.setData(data) + self.edit.show() + + def slotEdit(self): + item = self.connList.currentItem() + data = item.data(Qt.UserRole).toPyObject() + data = self.cleanDict(data) + self.edit.setData(data) + self.edit.show() + + def slotRemove(self): + item = self.connList.currentItem() + data = item.data(Qt.UserRole).toPyObject() + data = self.cleanDict(data) + self.emit(SIGNAL("removeConnection"), data) + + def slotConnect(self): + item = self.connList.currentItem() + data = item.data(Qt.UserRole).toPyObject() + data = self.cleanDict(data) + self.emit(SIGNAL("connect"), data) + + def cleanDict(self, data): + tmp = {} + for k, d in data.items(): + tmp[str(k)] = d + return tmp + + def slotSave(self, data): + self.emit(SIGNAL("saveConnection"), data) + + def slotItemDoubleClicked(self, defaultItem): + data = defaultItem.data(Qt.UserRole).toPyObject() + self.setDefault(data, True) + did = self.cleanDict(data)["id"] + allItems = self.connList.findItems("*", Qt.MatchWildcard) + count = self.connList.count() + for i in range(count): + item = self.connList.item(i) + data = item.data(Qt.UserRole).toPyObject() + if self.cleanDict(data)["id"] == did: + continue + self.setDefault(data, False) + + def setDefault(self, data, state): + data = self.cleanDict(data) + self.edit.setData(data) + data = self.edit.getData() + data["default"] = state + self.edit.emit(SIGNAL("save"), data) + + class EditWindow(QWidget): + def __init__(self): + QWidget.__init__(self) + + grid = QGridLayout() + + nameLabel = QLabel(_("Name:")) + hostLabel = QLabel(_("Host:")) + sslLabel = QLabel(_("SSL:")) + localLabel = QLabel(_("Local:")) + userLabel = QLabel(_("User:")) + pwLabel = QLabel(_("Password:")) + portLabel = QLabel(_("Port:")) + + name = QLineEdit() + host = QLineEdit() + ssl = QCheckBox() + local = QCheckBox() + user = QLineEdit() + password = QLineEdit() + password.setEchoMode(QLineEdit.Password) + port = QSpinBox() + port.setRange(1,10000) + + save = QPushButton(_("Save")) + cancel = QPushButton(_("Cancel")) + + grid.addWidget(nameLabel, 0, 0) + grid.addWidget(name, 0, 1) + grid.addWidget(localLabel, 1, 0) + grid.addWidget(local, 1, 1) + grid.addWidget(hostLabel, 2, 0) + grid.addWidget(host, 2, 1) + grid.addWidget(portLabel, 3, 0) + grid.addWidget(port, 3, 1) + grid.addWidget(sslLabel, 4, 0) + grid.addWidget(ssl, 4, 1) + grid.addWidget(userLabel, 5, 0) + grid.addWidget(user, 5, 1) + grid.addWidget(pwLabel, 6, 0) + grid.addWidget(password, 6, 1) + grid.addWidget(cancel, 7, 0) + grid.addWidget(save, 7, 1) + + self.setLayout(grid) + self.controls = {} + self.controls["name"] = name + self.controls["host"] = host + self.controls["ssl"] = ssl + self.controls["local"] = local + self.controls["user"] = user + self.controls["password"] = password + self.controls["port"] = port + self.controls["save"] = save + self.controls["cancel"] = cancel + + self.connect(cancel, SIGNAL("clicked()"), self.hide) + self.connect(save, SIGNAL("clicked()"), self.slotDone) + self.connect(local, SIGNAL("stateChanged(int)"), self.slotLocalChanged) + + self.id = None + self.default = None + + def setData(self, data): + self.id = data["id"] + self.default = data["default"] + self.controls["name"].setText(data["name"]) + if data["type"] == "local": + data["local"] = True + else: + data["local"] = False + self.controls["local"].setChecked(data["local"]) + if not data["local"]: + self.controls["ssl"].setChecked(data["ssl"]) + self.controls["user"].setText(data["user"]) + self.controls["password"].setText(data["password"]) + self.controls["port"].setValue(int(data["port"])) + self.controls["host"].setText(data["host"]) + self.controls["ssl"].setDisabled(False) + self.controls["user"].setDisabled(False) + self.controls["password"].setDisabled(False) + self.controls["port"].setDisabled(False) + self.controls["host"].setDisabled(False) + else: + self.controls["ssl"].setChecked(False) + self.controls["user"].setText("") + self.controls["port"].setValue(1) + self.controls["host"].setText("") + self.controls["ssl"].setDisabled(True) + self.controls["user"].setDisabled(True) + self.controls["password"].setDisabled(True) + self.controls["port"].setDisabled(True) + self.controls["host"].setDisabled(True) + + def slotLocalChanged(self, val): + if val == 2: + self.controls["ssl"].setDisabled(True) + self.controls["user"].setDisabled(True) + self.controls["password"].setDisabled(True) + self.controls["port"].setDisabled(True) + self.controls["host"].setDisabled(True) + elif val == 0: + self.controls["ssl"].setDisabled(False) + self.controls["user"].setDisabled(False) + self.controls["password"].setDisabled(False) + self.controls["port"].setDisabled(False) + self.controls["host"].setDisabled(False) + + def getData(self): + d = {} + d["id"] = self.id + d["default"] = self.default + d["name"] = self.controls["name"].text() + d["local"] = self.controls["local"].isChecked() + d["ssl"] = str(self.controls["ssl"].isChecked()) + d["user"] = self.controls["user"].text() + d["password"] = self.controls["password"].text() + d["host"] = self.controls["host"].text() + d["port"] = self.controls["port"].value() + if d["local"]: + d["type"] = "local" + else: + d["type"] = "remote" + return d + + def slotDone(self): + data = self.getData() + self.hide() + self.emit(SIGNAL("save"), data) + diff --git a/interfaces/gui/module/gui/CoreConfigParser.py b/interfaces/gui/module/gui/CoreConfigParser.py new file mode 100644 index 000000000..0d1d298c6 --- /dev/null +++ b/interfaces/gui/module/gui/CoreConfigParser.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- + +from __future__ import with_statement +from os.path import exists +from os.path import join + + +CONF_VERSION = 1 + +######################################################################## +class ConfigParser: + + #---------------------------------------------------------------------- + def __init__(self, configdir): + """Constructor""" + self.configdir = configdir + self.config = {} + + if self.checkVersion(): + self.readConfig() + + #---------------------------------------------------------------------- + def checkVersion(self): + + if not exists(join(self.configdir, "pyload.conf")): + return False + f = open(join(self.configdir, "pyload.conf"), "rb") + v = f.readline() + f.close() + v = v[v.find(":")+1:].strip() + + if int(v) < CONF_VERSION: + return False + + return True + + #---------------------------------------------------------------------- + def readConfig(self): + """reads the config file""" + + self.config = self.parseConfig(join(self.configdir, "pyload.conf")) + + + #---------------------------------------------------------------------- + def parseConfig(self, config): + """parses a given configfile""" + + f = open(config) + + config = f.read() + + config = config.split("\n")[1:] + + conf = {} + + section, option, value, typ, desc = "","","","","" + + listmode = False + + for line in config: + + line = line.rpartition("#") # removes comments + + if line[1]: + line = line[0] + else: + line = line[2] + + line = line.strip() + + try: + + if line == "": + continue + elif line.endswith(":"): + section, none, desc = line[:-1].partition('-') + section = section.strip() + desc = desc.replace('"', "").strip() + conf[section] = { "desc" : desc } + else: + if listmode: + + if line.endswith("]"): + listmode = False + line = line.replace("]","") + + value += [self.cast(typ, x.strip()) for x in line.split(",") if x] + + if not listmode: + conf[section][option] = { "desc" : desc, + "type" : typ, + "value" : value} + + + else: + content, none, value = line.partition("=") + + content, none, desc = content.partition(":") + + desc = desc.replace('"', "").strip() + + typ, option = content.split() + + value = value.strip() + + if value.startswith("["): + if value.endswith("]"): + listmode = False + value = value[:-1] + else: + listmode = True + + value = [self.cast(typ, x.strip()) for x in value[1:].split(",") if x] + else: + value = self.cast(typ, value) + + if not listmode: + conf[section][option] = { "desc" : desc, + "type" : typ, + "value" : value} + + except: + pass + + + f.close() + return conf + + #---------------------------------------------------------------------- + def cast(self, typ, value): + """cast value to given format""" + if type(value) not in (str, unicode): + return value + + if typ == "int": + return int(value) + elif typ == "bool": + return True if value.lower() in ("1","true", "on", "an","yes") else False + else: + return value + + #---------------------------------------------------------------------- + def get(self, section, option): + """get value""" + return self.config[section][option]["value"] + + #---------------------------------------------------------------------- + def __getitem__(self, section): + """provides dictonary like access: c['section']['option']""" + return Section(self, section) + +######################################################################## +class Section: + """provides dictionary like access for configparser""" + + #---------------------------------------------------------------------- + def __init__(self, parser, section): + """Constructor""" + self.parser = parser + self.section = section + + #---------------------------------------------------------------------- + def __getitem__(self, item): + """getitem""" + return self.parser.get(self.section, item) diff --git a/interfaces/gui/module/gui/LinkDock.py b/interfaces/gui/module/gui/LinkDock.py new file mode 100644 index 000000000..99429d04b --- /dev/null +++ b/interfaces/gui/module/gui/LinkDock.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +class NewLinkDock(QDockWidget): + def __init__(self): + QDockWidget.__init__(self, "New Links") + self.setObjectName("New Links Dock") + self.widget = NewLinkWindow(self) + self.setWidget(self.widget) + self.setAllowedAreas(Qt.RightDockWidgetArea|Qt.LeftDockWidgetArea) + self.hide() + + def slotDone(self): + text = str(self.widget.box.toPlainText()) + lines = text.splitlines() + self.emit(SIGNAL("done"), lines) + self.widget.box.clear() + self.hide() + +class NewLinkWindow(QWidget): + def __init__(self, dock): + QWidget.__init__(self) + self.dock = dock + self.setLayout(QVBoxLayout()) + layout = self.layout() + + boxLabel = QLabel("Paste URLs here:") + self.box = QTextEdit() + + save = QPushButton("Add") + + layout.addWidget(boxLabel) + layout.addWidget(self.box) + layout.addWidget(save) + + self.connect(save, SIGNAL("clicked()"), self.dock.slotDone) diff --git a/interfaces/gui/module/gui/MainWindow.py b/interfaces/gui/module/gui/MainWindow.py new file mode 100644 index 000000000..4ab840fed --- /dev/null +++ b/interfaces/gui/module/gui/MainWindow.py @@ -0,0 +1,512 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from module.gui.PackageDock import * +from module.gui.LinkDock import * +from module.gui.CaptchaDock import CaptchaDock +from module.gui.SettingsWidget import SettingsWidget + +from module.gui.Collector import CollectorView, Package, Link +from module.gui.Queue import QueueView +from module.gui.Accounts import AccountView + +class MainWindow(QMainWindow): + def __init__(self, connector): + """ + set up main window + """ + QMainWindow.__init__(self) + #window stuff + self.setWindowTitle(_("pyLoad Client")) + self.setWindowIcon(QIcon("icons/logo.png")) + self.resize(850,500) + + #layout version + self.version = 3 + + #init docks + self.newPackDock = NewPackageDock() + self.addDockWidget(Qt.RightDockWidgetArea, self.newPackDock) + self.connect(self.newPackDock, SIGNAL("done"), self.slotAddPackage) + self.captchaDock = CaptchaDock() + self.addDockWidget(Qt.BottomDockWidgetArea, self.captchaDock) + + #central widget, layout + self.masterlayout = QVBoxLayout() + lw = QWidget() + lw.setLayout(self.masterlayout) + self.setCentralWidget(lw) + + #set menubar and statusbar + self.menubar = self.menuBar() + self.statusbar = self.statusBar() + self.connect(self.statusbar, SIGNAL("showMsg"), self.statusbar.showMessage) + self.serverStatus = QLabel(_("Status: Not Connected")) + self.statusbar.addPermanentWidget(self.serverStatus) + + #menu + self.menus = {} + self.menus["file"] = self.menubar.addMenu(_("File")) + self.menus["connections"] = self.menubar.addMenu(_("Connections")) + + #menu actions + self.mactions = {} + self.mactions["exit"] = QAction(_("Exit"), self.menus["file"]) + self.mactions["manager"] = QAction(_("Connection manager"), self.menus["connections"]) + + #add menu actions + self.menus["file"].addAction(self.mactions["exit"]) + self.menus["connections"].addAction(self.mactions["manager"]) + + #toolbar + self.actions = {} + self.init_toolbar() + + #tabs + self.tabw = QTabWidget() + self.tabs = {} + self.tabs["queue"] = {"w":QWidget()} + self.tabs["collector"] = {"w":QWidget()} + self.tabs["accounts"] = {"w":QWidget()} + self.tabs["settings"] = {} + self.tabs["settings"]["s"] = QScrollArea() + self.tabs["settings"]["w"] = SettingsWidget() + self.tabs["settings"]["s"].setWidgetResizable(True) + self.tabs["settings"]["s"].setWidget(self.tabs["settings"]["w"]) + self.tabs["log"] = {"w":QWidget()} + self.tabw.addTab(self.tabs["queue"]["w"], _("Queue")) + self.tabw.addTab(self.tabs["collector"]["w"], _("Collector")) + self.tabw.addTab(self.tabs["accounts"]["w"], _("Accounts")) + self.tabw.addTab(self.tabs["settings"]["s"], _("Settings")) + self.tabw.addTab(self.tabs["log"]["w"], _("Log")) + + #init tabs + self.init_tabs(connector) + + self.setPriority = Priorty(self) + + #context menus + self.init_context() + + #layout + self.masterlayout.addWidget(self.tabw) + + #signals.. + self.connect(self.mactions["manager"], SIGNAL("triggered()"), self.slotShowConnector) + self.connect(self.mactions["exit"], SIGNAL("triggered()"), self.close) + + self.connect(self.tabs["queue"]["view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotQueueContextMenu) + self.connect(self.tabs["collector"]["package_view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotCollectorContextMenu) + + self.connect(self.tabw, SIGNAL("currentChanged(int)"), self.slotTabChanged) + + self.lastAddedID = None + + def init_toolbar(self): + """ + create toolbar + """ + self.toolbar = self.addToolBar(_("Main Toolbar")) + self.toolbar.setObjectName("Main Toolbar") + self.toolbar.setIconSize(QSize(40,40)) + self.actions["toggle_status"] = self.toolbar.addAction(_("Toggle Pause/Resume")) + pricon = QIcon() + pricon.addFile("icons/toolbar_start.png", QSize(), QIcon.Normal, QIcon.Off) + pricon.addFile("icons/toolbar_pause.png", QSize(), QIcon.Normal, QIcon.On) + self.actions["toggle_status"].setIcon(pricon) + self.actions["toggle_status"].setCheckable(True) + self.actions["status_stop"] = self.toolbar.addAction(QIcon("icons/toolbar_stop.png"), _("Stop")) + self.toolbar.addSeparator() + self.actions["add"] = self.toolbar.addAction(QIcon("icons/toolbar_add.png"), _("Add")) + self.toolbar.addSeparator() + self.actions["clipboard"] = self.toolbar.addAction(QIcon("icons/clipboard.png"), _("Check Clipboard")) + self.actions["clipboard"].setCheckable(True) + + self.connect(self.actions["toggle_status"], SIGNAL("toggled(bool)"), self.slotToggleStatus) + self.connect(self.actions["clipboard"], SIGNAL("toggled(bool)"), self.slotToggleClipboard) + self.connect(self.actions["status_stop"], SIGNAL("triggered()"), self.slotStatusStop) + self.addMenu = QMenu() + packageAction = self.addMenu.addAction(_("Package")) + containerAction = self.addMenu.addAction(_("Container")) + self.connect(self.actions["add"], SIGNAL("triggered()"), self.slotAdd) + self.connect(packageAction, SIGNAL("triggered()"), self.slotShowAddPackage) + self.connect(containerAction, SIGNAL("triggered()"), self.slotShowAddContainer) + + def init_tabs(self, connector): + """ + create tabs + """ + #queue + self.tabs["queue"]["l"] = QGridLayout() + self.tabs["queue"]["w"].setLayout(self.tabs["queue"]["l"]) + self.tabs["queue"]["view"] = QueueView(connector) + self.tabs["queue"]["l"].addWidget(self.tabs["queue"]["view"]) + + #collector + toQueue = QPushButton(_("Push selected packages to queue")) + self.tabs["collector"]["l"] = QGridLayout() + self.tabs["collector"]["w"].setLayout(self.tabs["collector"]["l"]) + self.tabs["collector"]["package_view"] = CollectorView(connector) + self.tabs["collector"]["l"].addWidget(self.tabs["collector"]["package_view"], 0, 0) + self.tabs["collector"]["l"].addWidget(toQueue, 1, 0) + self.connect(toQueue, SIGNAL("clicked()"), self.slotPushPackageToQueue) + self.tabs["collector"]["package_view"].setContextMenuPolicy(Qt.CustomContextMenu) + self.tabs["queue"]["view"].setContextMenuPolicy(Qt.CustomContextMenu) + + #log + self.tabs["log"]["l"] = QGridLayout() + self.tabs["log"]["w"].setLayout(self.tabs["log"]["l"]) + self.tabs["log"]["text"] = QTextEdit() + self.tabs["log"]["text"].logOffset = 0 + self.tabs["log"]["text"].setReadOnly(True) + self.connect(self.tabs["log"]["text"], SIGNAL("append(QString)"), self.tabs["log"]["text"].append) + self.tabs["log"]["l"].addWidget(self.tabs["log"]["text"]) + + #accounts + self.tabs["accounts"]["view"] = AccountView(connector) + self.tabs["accounts"]["w"].setLayout(QHBoxLayout()) + self.tabs["accounts"]["w"].layout().addWidget(self.tabs["accounts"]["view"]) + + def init_context(self): + """ + create context menus + """ + self.activeMenu = None + #queue + self.queueContext = QMenu() + self.queueContext.buttons = {} + self.queueContext.item = (None, None) + self.queueContext.buttons["remove"] = QAction(QIcon("icons/remove_small.png"), _("Remove"), self.queueContext) + self.queueContext.buttons["restart"] = QAction(QIcon("icons/refresh_small.png"), _("Restart"), self.queueContext) + self.queueContext.buttons["pull"] = QAction(QIcon("icons/pull_small.png"), _("Pull out"), self.queueContext) + self.queueContext.buttons["abort"] = QAction(QIcon("icons/abort.png"), _("Abort"), self.queueContext) + self.queueContext.buttons["edit"] = QAction(QIcon("icons/edit_small.png"), _("Edit Name"), self.queueContext) + self.queuePriorityMenu = QMenu(_("Priority")) + self.queuePriorityMenu.actions = {} + self.queuePriorityMenu.actions["veryhigh"] = QAction(_("very high"), self.queuePriorityMenu) + self.queuePriorityMenu.addAction(self.queuePriorityMenu.actions["veryhigh"]) + self.queuePriorityMenu.actions["high"] = QAction(_("high"), self.queuePriorityMenu) + self.queuePriorityMenu.addAction(self.queuePriorityMenu.actions["high"]) + self.queuePriorityMenu.actions["normal"] = QAction(_("normal"), self.queuePriorityMenu) + self.queuePriorityMenu.addAction(self.queuePriorityMenu.actions["normal"]) + self.queuePriorityMenu.actions["low"] = QAction(_("low"), self.queuePriorityMenu) + self.queuePriorityMenu.addAction(self.queuePriorityMenu.actions["low"]) + self.queuePriorityMenu.actions["verylow"] = QAction(_("very low"), self.queuePriorityMenu) + self.queuePriorityMenu.addAction(self.queuePriorityMenu.actions["verylow"]) + self.queueContext.addAction(self.queueContext.buttons["pull"]) + self.queueContext.addAction(self.queueContext.buttons["edit"]) + self.queueContext.addAction(self.queueContext.buttons["remove"]) + self.queueContext.addAction(self.queueContext.buttons["restart"]) + self.queueContext.addAction(self.queueContext.buttons["abort"]) + self.queueContext.addMenu(self.queuePriorityMenu) + self.connect(self.queueContext.buttons["remove"], SIGNAL("triggered()"), self.slotRemoveDownload) + self.connect(self.queueContext.buttons["restart"], SIGNAL("triggered()"), self.slotRestartDownload) + self.connect(self.queueContext.buttons["pull"], SIGNAL("triggered()"), self.slotPullOutPackage) + self.connect(self.queueContext.buttons["abort"], SIGNAL("triggered()"), self.slotAbortDownload) + self.connect(self.queueContext.buttons["edit"], SIGNAL("triggered()"), self.slotEditPackage) + + self.connect(self.queuePriorityMenu.actions["veryhigh"], SIGNAL("triggered()"), self.setPriority.veryHigh) + self.connect(self.queuePriorityMenu.actions["high"], SIGNAL("triggered()"), self.setPriority.high) + self.connect(self.queuePriorityMenu.actions["normal"], SIGNAL("triggered()"), self.setPriority.normal) + self.connect(self.queuePriorityMenu.actions["low"], SIGNAL("triggered()"), self.setPriority.low) + self.connect(self.queuePriorityMenu.actions["verylow"], SIGNAL("triggered()"), self.setPriority.veryLow) + + #collector + self.collectorContext = QMenu() + self.collectorContext.buttons = {} + self.collectorContext.item = (None, None) + self.collectorContext.buttons["remove"] = QAction(QIcon("icons/remove_small.png"), _("Remove"), self.collectorContext) + self.collectorContext.buttons["push"] = QAction(QIcon("icons/push_small.png"), _("Push to queue"), self.collectorContext) + self.collectorContext.buttons["edit"] = QAction(QIcon("icons/edit_small.png"), _("Edit Name"), self.collectorContext) + self.collectorContext.addAction(self.collectorContext.buttons["push"]) + self.collectorContext.addAction(self.collectorContext.buttons["edit"]) + self.collectorContext.addAction(self.collectorContext.buttons["remove"]) + self.connect(self.collectorContext.buttons["remove"], SIGNAL("triggered()"), self.slotRemoveDownload) + self.connect(self.collectorContext.buttons["push"], SIGNAL("triggered()"), self.slotPushPackageToQueue) + self.connect(self.collectorContext.buttons["edit"], SIGNAL("triggered()"), self.slotEditPackage) + + def slotToggleStatus(self, status): + """ + pause/start toggle (toolbar) + """ + self.emit(SIGNAL("setDownloadStatus"), status) + + def slotStatusStop(self): + """ + stop button (toolbar) + """ + self.emit(SIGNAL("stopAllDownloads")) + + def slotAdd(self): + """ + add button (toolbar) + show context menu (choice: links/package) + """ + self.addMenu.exec_(QCursor.pos()) + + def slotShowAddPackage(self): + """ + action from add-menu + show new-package dock + """ + self.tabw.setCurrentIndex(1) + self.newPackDock.show() + + def slotShowAddLinks(self): + """ + action from add-menu + show new-links dock + """ + self.tabw.setCurrentIndex(1) + self.newLinkDock.show() + + def slotShowConnector(self): + """ + connectionmanager action triggered + let main to the stuff + """ + self.emit(SIGNAL("connector")) + + def slotAddPackage(self, name, links): + """ + new package + let main to the stuff + """ + self.emit(SIGNAL("addPackage"), name, links) + + def slotShowAddContainer(self): + """ + action from add-menu + show file selector, emit upload + """ + typeStr = ";;".join([ + _("All Container Types (%s)") % "*.dlc *.ccf *.rsdf *.txt", + _("DLC (%s)") % "*.dlc", + _("CCF (%s)") % "*.ccf", + _("RSDF (%s)") % "*.rsdf", + _("Text Files (%s)") % "*.txt" + ]) + fileNames = QFileDialog.getOpenFileNames(self, _("Open container"), "", typeStr) + for name in fileNames: + self.emit(SIGNAL("addContainer"), str(name)) + + def slotPushPackageToQueue(self): + """ + push collector pack to queue + get child ids + let main to the rest + """ + smodel = self.tabs["collector"]["package_view"].selectionModel() + for index in smodel.selectedRows(0): + item = index.internalPointer() + if isinstance(item, Package): + self.emit(SIGNAL("pushPackageToQueue"), item.id) + else: + self.emit(SIGNAL("pushPackageToQueue"), item.package.id) + + def saveWindow(self): + """ + get window state/geometry + pass data to main + """ + state_raw = self.saveState(self.version) + geo_raw = self.saveGeometry() + + state = str(state_raw.toBase64()) + geo = str(geo_raw.toBase64()) + + self.emit(SIGNAL("saveMainWindow"), state, geo) + + def closeEvent(self, event): + """ + somebody wants to close me! + let me first save my state + """ + self.saveWindow() + event.accept() + self.emit(SIGNAL("quit")) + + def restoreWindow(self, state, geo): + """ + restore window state/geometry + """ + state = QByteArray(state) + geo = QByteArray(geo) + + state_raw = QByteArray.fromBase64(state) + geo_raw = QByteArray.fromBase64(geo) + + self.restoreState(state_raw, self.version) + self.restoreGeometry(geo_raw) + + def slotQueueContextMenu(self, pos): + """ + custom context menu in queue view requested + """ + globalPos = self.tabs["queue"]["view"].mapToGlobal(pos) + i = self.tabs["queue"]["view"].indexAt(pos) + if not i: + return + item = i.internalPointer() + menuPos = QCursor.pos() + menuPos.setX(menuPos.x()+2) + self.activeMenu = self.queueContext + showAbort = False + if isinstance(item, Link) and item.data["downloading"]: + showAbort = True + elif isinstance(item, Package): + for child in item.children: + if child.data["downloading"]: + showAbort = True + if showAbort: + self.queueContext.buttons["abort"].setVisible(True) + else: + self.queueContext.buttons["abort"].setVisible(False) + if isinstance(item, Package): + self.queueContext.index = i + self.queueContext.buttons["edit"].setVisible(True) + else: + self.queueContext.index = None + self.queueContext.buttons["edit"].setVisible(False) + self.queueContext.exec_(menuPos) + + def slotCollectorContextMenu(self, pos): + """ + custom context menu in package collector view requested + """ + globalPos = self.tabs["collector"]["package_view"].mapToGlobal(pos) + i = self.tabs["collector"]["package_view"].indexAt(pos) + if not i: + return + item = i.internalPointer() + menuPos = QCursor.pos() + menuPos.setX(menuPos.x()+2) + self.activeMenu = self.collectorContext + if isinstance(item, Package): + self.collectorContext.index = i + self.collectorContext.buttons["edit"].setVisible(True) + else: + self.collectorContext.index = None + self.collectorContext.buttons["edit"].setVisible(False) + self.collectorContext.exec_(menuPos) + + def slotLinkCollectorContextMenu(self, pos): + """ + custom context menu in link collector view requested + """ + pass + + def slotRestartDownload(self): + """ + restart download action is triggered + """ + smodel = self.tabs["queue"]["view"].selectionModel() + for index in smodel.selectedRows(0): + item = index.internalPointer() + self.emit(SIGNAL("restartDownload"), item.id, isinstance(item, Package)) + id, isTopLevel = self.queueContext.item + if not id == None: + self.emit(SIGNAL("restartDownload"), id, isTopLevel) + + def slotRemoveDownload(self): + """ + remove download action is triggered + """ + if self.activeMenu == self.queueContext: + view = self.tabs["queue"]["view"] + else: + view = self.tabs["collector"]["package_view"] + smodel = view.selectionModel() + for index in smodel.selectedRows(0): + item = index.internalPointer() + self.emit(SIGNAL("removeDownload"), item.id, isinstance(item, Package)) + + def slotToggleClipboard(self, status): + """ + check clipboard (toolbar) + """ + self.emit(SIGNAL("setClipboardStatus"), status) + + def slotEditPackage(self): + if self.activeMenu == self.queueContext: + view = self.tabs["queue"]["view"] + else: + view = self.tabs["collector"]["package_view"] + view.edit(self.activeMenu.index) + + def slotEditCommit(self, editor): + self.emit(SIGNAL("changePackageName"), self.activeMenu.index.internalPointer().id, editor.text()) + + def slotPullOutPackage(self): + """ + pull package out of the queue + """ + smodel = self.tabs["queue"]["view"].selectionModel() + for index in smodel.selectedRows(0): + item = index.internalPointer() + if isinstance(item, Package): + self.emit(SIGNAL("pullOutPackage"), item.id) + else: + self.emit(SIGNAL("pullOutPackage"), item.package.id) + + def slotAbortDownload(self): + view = self.tabs["queue"]["view"] + smodel = view.selectionModel() + for index in smodel.selectedRows(0): + item = index.internalPointer() + self.emit(SIGNAL("abortDownload"), item.id, isinstance(item, Package)) + + def changeEvent(self, e): + if e.type() == QEvent.WindowStateChange and self.isMinimized(): + e.ignore() + self.hide() + self.emit(SIGNAL("hidden")) + else: + super(MainWindow, self).changeEvent(e) + + def slotTabChanged(self, index): + if index == 2: + self.emit(SIGNAL("reloadAccounts")) + elif index == 3: + self.tabs["settings"]["w"].loadConfig() + +class Priorty(): + def __init__(self, win): + self.w = win + + def setPriority(self, level): + if self.w.activeMenu == self.w.queueContext: + smodel = self.w.tabs["queue"]["view"].selectionModel() + else: + smodel = self.w.tabs["collector"]["package_view"].selectionModel() + for index in smodel.selectedRows(0): + item = index.internalPointer() + pid = item.id if isinstance(item, Package) else item.package.id + self.w.emit(SIGNAL("setPriority"), pid, level) + + def veryHigh(self): self.setPriority(2) + def high(self): self.setPriority(1) + def normal(self): self.setPriority(0) + def low(self): self.setPriority(-1) + def veryLow(self): self.setPriority(-2) + + + diff --git a/interfaces/gui/module/gui/PackageDock.py b/interfaces/gui/module/gui/PackageDock.py new file mode 100644 index 000000000..8bd965f16 --- /dev/null +++ b/interfaces/gui/module/gui/PackageDock.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +class NewPackageDock(QDockWidget): + def __init__(self): + QDockWidget.__init__(self, _("New Package")) + self.setObjectName("New Package Dock") + self.widget = NewPackageWindow(self) + self.setWidget(self.widget) + self.setAllowedAreas(Qt.RightDockWidgetArea|Qt.LeftDockWidgetArea) + self.hide() + + def slotDone(self): + text = str(self.widget.box.toPlainText()) + lines = [] + for line in text.splitlines(): + line = line.strip() + if not line: + continue + lines.append(line) + self.emit(SIGNAL("done"), str(self.widget.nameInput.text()), lines) + self.widget.nameInput.setText("") + self.widget.box.clear() + self.hide() + +class NewPackageWindow(QWidget): + def __init__(self, dock): + QWidget.__init__(self) + self.dock = dock + self.setLayout(QGridLayout()) + layout = self.layout() + + nameLabel = QLabel(_("Name")) + nameInput = QLineEdit() + + linksLabel = QLabel(_("Links in this Package")) + + self.box = QTextEdit() + self.nameInput = nameInput + + save = QPushButton(_("Create")) + + layout.addWidget(nameLabel, 0, 0) + layout.addWidget(nameInput, 0, 1) + layout.addWidget(linksLabel, 1, 0, 1, 2) + layout.addWidget(self.box, 2, 0, 1, 2) + layout.addWidget(save, 3, 0, 1, 2) + + self.connect(save, SIGNAL("clicked()"), self.dock.slotDone) diff --git a/interfaces/gui/module/gui/Queue.py b/interfaces/gui/module/gui/Queue.py new file mode 100644 index 000000000..8b6f679f8 --- /dev/null +++ b/interfaces/gui/module/gui/Queue.py @@ -0,0 +1,252 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from time import sleep, time + +from module.gui.Collector import CollectorModel, Package, Link, CollectorView, statusMap, statusMapReverse + +class QueueModel(CollectorModel): + def __init__(self, view, connector): + CollectorModel.__init__(self, view, connector) + self.cols = 5 + self.wait_dict = {} + + self.updater = self.QueueUpdater(self.interval) + self.connect(self.updater, SIGNAL("update()"), self.update) + + class QueueUpdater(QObject): + def __init__(self, interval): + QObject.__init__(self) + + self.interval = interval + self.timer = QTimer() + self.timer.connect(self.timer, SIGNAL("timeout()"), self, SIGNAL("update()")) + + def start(self): + self.timer.start(1000) + + def stop(self): + self.timer.stop() + + def start(self): + self.updater.start() + + def stop(self): + self.updater.stop() + + def fullReload(self): + self._data = [] + packs = self.connector.getPackageQueue() + self.beginInsertRows(QModelIndex(), 0, len(packs)) + for pid, data in packs.items(): + package = Package(pid, data) + self._data.append(package) + self._data = sorted(self._data, key=lambda p: p.data["order"]) + self.endInsertRows() + + def update(self): + locker = QMutexLocker(self.mutex) + downloading = self.connector.getDownloadQueue() + for p, pack in enumerate(self._data): + for d in downloading: + child = pack.getChild(d["id"]) + if child: + child.data["downloading"] = d + k = pack.getChildKey(d["id"]) + self.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), self.index(k, 0, self.index(p, 0)), self.index(k, self.cols, self.index(p, self.cols))) + + def headerData(self, section, orientation, role=Qt.DisplayRole): + if orientation == Qt.Horizontal and role == Qt.DisplayRole: + if section == 0: + return QVariant(_("Name")) + elif section == 2: + return QVariant(_("Status")) + elif section == 1: + return QVariant(_("Plugin")) + elif section == 3: + return QVariant(_("Priority")) + elif section == 4: + return QVariant(_("Progress")) + return QVariant() + + def getWaitingProgress(self, item): + locker = QMutexLocker(self.mutex) + if isinstance(item, Link): + if item.data["status"] == 5 and item.data["downloading"]: + until = float(item.data["downloading"]["wait_until"]) + try: + since, until_old = self.wait_dict[item.id] + if not until == until_old: + raise Exception + except: + since = time() + self.wait_dict[item.id] = since, until + since = float(since) + max_wait = float(until-since) + rest = int(until-time()) + res = 100/max_wait + perc = rest*res + return perc, rest + return None + + def getProgress(self, item): + locker = QMutexLocker(self.mutex) + if isinstance(item, Link): + if item.data["downloading"]: + return int(item.data["downloading"]["percent"]) + if item.data["statusmsg"] == "finished" or \ + item.data["statusmsg"] == "failed" or \ + item.data["statusmsg"] == "aborted": + return 100 + elif isinstance(item, Package): + count = len(item.children) + perc_sum = 0 + for child in item.children: + val = 0 + if child.data["downloading"]: + val = int(child.data["downloading"]["percent"]) + elif child.data["statusmsg"] == "finished" or \ + child.data["statusmsg"] == "failed" or \ + child.data["statusmsg"] == "aborted": + val = 100 + perc_sum += val + if count == 0: + return 0 + return perc_sum/count + return 0 + + def getSpeed(self, item): + if isinstance(item, Link): + if item.data["downloading"]: + return int(item.data["downloading"]["speed"]) + elif isinstance(item, Package): + count = len(item.children) + speed_sum = 0 + all_waiting = True + running = False + for child in item.children: + val = 0 + if child.data["downloading"]: + if not child.data["statusmsg"] == "waiting": + all_waiting = False + val = int(child.data["downloading"]["speed"]) + running = True + speed_sum += val + if count == 0 or not running or all_waiting: + return None + return speed_sum + return None + + def data(self, index, role=Qt.DisplayRole): + if not index.isValid(): + return QVariant() + if role == Qt.DisplayRole: + if index.column() == 0: + return QVariant(index.internalPointer().data["name"]) + elif index.column() == 1: + item = index.internalPointer() + plugins = [] + if isinstance(item, Package): + for child in item.children: + if not child.data["plugin"] in plugins: + plugins.append(child.data["plugin"]) + else: + plugins.append(item.data["plugin"]) + return QVariant(", ".join(plugins)) + elif index.column() == 2: + item = index.internalPointer() + status = 0 + speed = self.getSpeed(item) + if isinstance(item, Package): + for child in item.children: + if child.data["status"] > status: + status = child.data["status"] + else: + status = item.data["status"] + + if speed == None or status == 7 or status == 10 or status == 5: + return QVariant(statusMapReverse[status]) + else: + return QVariant("%s (%s KB/s)" % (statusMapReverse[status], speed)) + elif index.column() == 3: + item = index.internalPointer() + if isinstance(item, Package): + return QVariant(item.data["priority"]) + elif role == Qt.EditRole: + if index.column() == 0: + return QVariant(index.internalPointer().data["name"]) + return QVariant() + + def flags(self, index): + if index.column() == 0 and self.parent(index) == QModelIndex(): + return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled + return Qt.ItemIsSelectable | Qt.ItemIsEnabled + +class QueueView(CollectorView): + def __init__(self, connector): + CollectorView.__init__(self, connector) + self.setModel(QueueModel(self, connector)) + + self.setColumnWidth(0, 300) + self.setColumnWidth(1, 100) + self.setColumnWidth(2, 150) + self.setColumnWidth(3, 50) + self.setColumnWidth(4, 100) + + self.setEditTriggers(QAbstractItemView.NoEditTriggers) + + self.delegate = QueueProgressBarDelegate(self, self.model()) + self.setItemDelegateForColumn(4, self.delegate) + +class QueueProgressBarDelegate(QItemDelegate): + def __init__(self, parent, queue): + QItemDelegate.__init__(self, parent) + self.queue = queue + + def paint(self, painter, option, index): + if not index.isValid(): + return + if index.column() == 4: + item = index.internalPointer() + w = self.queue.getWaitingProgress(item) + wait = None + if w: + progress = w[0] + wait = w[1] + else: + progress = self.queue.getProgress(item) + opts = QStyleOptionProgressBarV2() + opts.maximum = 100 + opts.minimum = 0 + opts.progress = progress + opts.rect = option.rect + opts.rect.setRight(option.rect.right()-1) + opts.rect.setHeight(option.rect.height()-1) + opts.textVisible = True + opts.textAlignment = Qt.AlignCenter + if not wait == None: + opts.text = QString("waiting %d seconds" % (wait,)) + else: + opts.text = QString.number(opts.progress) + "%" + QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) + return + QItemDelegate.paint(self, painter, option, index) + diff --git a/interfaces/gui/module/gui/SettingsWidget.py b/interfaces/gui/module/gui/SettingsWidget.py new file mode 100644 index 000000000..6197cee6c --- /dev/null +++ b/interfaces/gui/module/gui/SettingsWidget.py @@ -0,0 +1,108 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +from PyQt4.QtCore import * +from PyQt4.QtGui import * +from sip import delete + +class SettingsWidget(QWidget): + def __init__(self): + QWidget.__init__(self) + self.connector = None + self.sections = {} + self.psections = {} + self.data = None + self.pdata = None + self.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored) + + def setConnector(self, connector): + self.connector = connector + + def loadConfig(self): + if self.layout(): + delete(self.layout()) + for s in self.sections.values()+self.psections.values(): + delete(s) + self.sections = {} + self.setLayout(QVBoxLayout()) + self.clearConfig() + layout = self.layout() + layout.setSizeConstraint(QLayout.SetMinAndMaxSize) + + self.data = self.connector.proxy.get_config() + self.pdata = self.connector.proxy.get_plugin_config() + for k, section in self.data.items(): + s = Section(section, self) + self.sections[k] = s + layout.addWidget(s) + for k, section in self.pdata.items(): + s = Section(section, self, "plugin") + self.psections[k] = s + layout.addWidget(s) + + rel = QPushButton(_("Reload")) + layout.addWidget(rel) + save = QPushButton(_("Save")) + #layout.addWidget(save) + self.connect(rel, SIGNAL("clicked()"), self.loadConfig) + + def clearConfig(self): + self.sections = {} + +class Section(QGroupBox): + def __init__(self, data, parent, ctype="core"): + self.data = data + QGroupBox.__init__(self, data["desc"], parent) + self.labels = {} + self.inputs = {} + self.ctype = ctype + layout = QGridLayout(self) + self.setLayout(layout) + + row = 0 + for k, option in self.data.items(): + if k == "desc": + continue + l = QLabel(option["desc"], self) + l.setMinimumWidth(400) + self.labels[k] = l + layout.addWidget(l, row, 0) + if option["type"] == "int": + i = QSpinBox(self) + i.setMaximum(999999) + i.setValue(int(option["value"])) + elif not option["type"].find(";") == -1: + choices = option["type"].split(";") + i = QComboBox(self) + i.addItems(choices) + i.setCurrentIndex(i.findText(option["value"])) + elif option["type"] == "bool": + i = QComboBox(self) + i.addItem(_("Yes"), QVariant(True)) + i.addItem(_("No"), QVariant(False)) + if option["value"]: + i.setCurrentIndex(0) + else: + i.setCurrentIndex(1) + else: + i = QLineEdit(self) + i.setText(option["value"]) + self.inputs[k] = i + #i.setMaximumWidth(300) + layout.addWidget(i, row, 1) + row += 1 diff --git a/interfaces/gui/module/gui/XMLParser.py b/interfaces/gui/module/gui/XMLParser.py new file mode 100644 index 000000000..5e3b7bf65 --- /dev/null +++ b/interfaces/gui/module/gui/XMLParser.py @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" +from __future__ import with_statement + +from PyQt4.QtCore import * +from PyQt4.QtGui import * +from PyQt4.QtXml import * + +import os + +class XMLParser(): + def __init__(self, data, dfile=""): + self.mutex = QMutex() + self.mutex.lock() + self.xml = QDomDocument() + self.file = data + self.dfile = dfile + self.mutex.unlock() + self.loadData() + self.root = self.xml.documentElement() + + def loadData(self): + self.mutex.lock() + f = self.file + if not os.path.exists(f): + f = self.dfile + with open(f, 'r') as fh: + content = fh.read() + self.xml.setContent(content) + self.mutex.unlock() + + def saveData(self): + self.mutex.lock() + content = self.xml.toString() + with open(self.file, 'w') as fh: + fh.write(content) + self.mutex.unlock() + return content + + def parseNode(self, node, ret_type="list"): + if ret_type == "dict": + childNodes = {} + else: + childNodes = [] + child = node.firstChild() + while True: + n = child.toElement() + if n.isNull(): + break + else: + if ret_type == "dict": + childNodes[str(n.tagName())] = n + else: + childNodes.append(n) + child = child.nextSibling() + return childNodes diff --git a/interfaces/gui/module/gui/__init__.py b/interfaces/gui/module/gui/__init__.py new file mode 100644 index 000000000..8d1c8b69c --- /dev/null +++ b/interfaces/gui/module/gui/__init__.py @@ -0,0 +1 @@ + diff --git a/interfaces/gui/module/gui/connector.py b/interfaces/gui/module/gui/connector.py new file mode 100644 index 000000000..975e1ca1b --- /dev/null +++ b/interfaces/gui/module/gui/connector.py @@ -0,0 +1,311 @@ +# -*- coding: utf-8 -*- +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay +""" + +SERVER_VERSION = "0.4.1-dev" + +from time import sleep +from uuid import uuid4 as uuid + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from xmlrpclib import ServerProxy +import socket + +class Connector(QThread): + def __init__(self): + QThread.__init__(self) + self.mutex = QMutex() + self.addr = None + self.errorQueue = [] + self.connectionID = None + self.running = True + self.proxy = self.Dummy() + + def setAddr(self, addr): + """ + set new address + """ + self.mutex.lock() + self.addr = addr + self.mutex.unlock() + + def connectProxy(self): + self.proxy = DispatchRPC(self.mutex, ServerProxy(self.addr, allow_none=True, verbose=False)) + self.connect(self.proxy, SIGNAL("proxy_error"), self._proxyError) + self.connect(self.proxy, SIGNAL("connectionLost"), self, SIGNAL("connectionLost")) + try: + server_version = self.proxy.get_server_version() + self.connectionID = uuid().hex + except: + return False + if not server_version: + return False + elif not server_version == SERVER_VERSION: + self.emit(SIGNAL("error_box"), "server is version %s client accepts version %s" % (server_version, SERVER_VERSION)) + return False + return True + + def canConnect(self): + return self.connectProxy() + + def _proxyError(self, func, e): + """ + formats proxy error msg + """ + msg = "proxy error in '%s':\n%s" % (func, e) + self.errorQueue.append(msg) + + def getError(self): + self.mutex.lock() + if len(self.errorQueue) > 0: + err = self.errorQueue.pop() + print err + self.emit(SIGNAL("error_box"), err) + self.mutex.unlock() + + def stop(self): + """ + stop thread + """ + self.running = False + + def run(self): + """ + start thread + (called from thread.start()) + """ + self.canConnect() + while self.running: + sleep(1) + self.getError() + + class Dummy(object): + def __getattr__(self, attr): + def dummy(*args, **kwargs): + return None + return dummy + + def getPackageCollector(self): + """ + grab packages from collector and return the data + """ + return self.proxy.get_collector() + + def getLinkInfo(self, id): + """ + grab file info for the given id and return it + """ + w = self.proxy.get_file_info + w.error = False + info = w(id) + if not info: return None + info["downloading"] = None + return info + + def getPackageInfo(self, id): + """ + grab package info for the given id and return it + """ + w = self.proxy.get_package_data + w.error = False + return w(id) + + def getPackageQueue(self): + """ + grab queue return the data + """ + return self.proxy.get_queue() + + def getPackageFiles(self, id): + """ + grab package files and return ids + """ + return self.proxy.get_package_files(id) + + def getDownloadQueue(self): + """ + grab files that are currently downloading and return info + """ + return self.proxy.status_downloads() + + def getServerStatus(self): + """ + return server status + """ + return self.proxy.status_server() + + def addURLs(self, links): + """ + add links to collector + """ + self.proxy.add_urls(links) + + def togglePause(self): + """ + toogle pause + """ + return self.proxy.toggle_pause() + + def setPause(self, pause): + """ + set pause + """ + if pause: + self.proxy.pause_server() + else: + self.proxy.unpause_server() + + def newPackage(self, name): + """ + create a new package and return id + """ + return self.proxy.new_package(name) + + def addFileToPackage(self, fileid, packid): + """ + add a file from collector to package + """ + self.proxy.move_file_2_package(fileid, packid) + + def pushPackageToQueue(self, packid): + """ + push a package to queue + """ + self.proxy.push_package_2_queue(packid) + + def restartPackage(self, packid): + """ + restart a package + """ + self.proxy.restart_package(packid) + + def restartFile(self, fileid): + """ + restart a file + """ + self.proxy.restart_file(fileid) + + def removePackage(self, packid): + """ + remove a package + """ + self.proxy.del_packages([packid,]) + + def removeFile(self, fileid): + """ + remove a file + """ + self.proxy.del_links([fileid,]) + + def uploadContainer(self, filename, type, content): + """ + upload a container + """ + self.proxy.upload_container(filename, type, content) + + def getLog(self, offset): + """ + get log + """ + return self.proxy.get_log(offset) + + def stopAllDownloads(self): + """ + get log + """ + self.proxy.pause_server() + self.proxy.stop_downloads() + + def updateAvailable(self): + """ + update available + """ + return self.proxy.update_available() + + def setPackageName(self, pid, name): + """ + set new package name + """ + return self.proxy.set_package_name(pid, name) + + def pullOutPackage(self, pid): + """ + pull out package + """ + return self.proxy.pull_out_package(pid) + + def captchaWaiting(self): + """ + is the a captcha waiting? + """ + return self.proxy.is_captcha_waiting() + + def getCaptcha(self): + """ + get captcha + """ + return self.proxy.get_captcha_task() + + def setCaptchaResult(self, cid, result): + """ + get captcha + """ + return self.proxy.set_captcha_result(cid, result) + + def getCaptchaStatus(self, cid): + """ + get captcha status + """ + return self.proxy.get_task_status(cid) + + def getEvents(self): + """ + get events + """ + return self.proxy.get_events(self.connectionID) + +class DispatchRPC(QObject): + def __init__(self, mutex, server): + QObject.__init__(self) + self.mutex = mutex + self.server = server + + def __getattr__(self, attr): + self.mutex.lock() + self.fname = attr + f = self.Wrapper(getattr(self.server, attr), self.mutex, self) + return f + + class Wrapper(object): + def __init__(self, f, mutex, dispatcher): + self.f = f + self.mutex = mutex + self.dispatcher = dispatcher + self.error = True + + def __call__(self, *args, **kwargs): + try: + return self.f(*args, **kwargs) + except socket.error: + self.dispatcher.emit(SIGNAL("connectionLost")) + except Exception, e: + if self.error: + self.dispatcher.emit(SIGNAL("proxy_error"), self.dispatcher.fname, e) + finally: + self.mutex.unlock() diff --git a/interfaces/gui/pyLoadGui.py b/interfaces/gui/pyLoadGui.py new file mode 100755 index 000000000..5dc0f8024 --- /dev/null +++ b/interfaces/gui/pyLoadGui.py @@ -0,0 +1,725 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" + 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 3 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, see <http://www.gnu.org/licenses/>. + + @author: mkaay + @version: v0.4.0 +""" + +import sys + +from time import sleep + +from PyQt4.QtCore import * +from PyQt4.QtGui import * + +from uuid import uuid4 as uuid +import re +import gettext +from xmlrpclib import Binary + +from module.gui.ConnectionManager import * +from module.gui.connector import Connector +from module.gui.MainWindow import * +from module.gui.Queue import * +from module.gui.Collector import * +from module.gui.XMLParser import * +from module.gui.CoreConfigParser import ConfigParser + +from os.path import expanduser +from os.path import join +from os.path import basename +from os.path import dirname +from os import chdir +from os import makedirs +from os import name as platform + +try: + import pynotify +except ImportError: + pass + +class main(QObject): + def __init__(self): + """ + main setup + """ + QObject.__init__(self) + self.app = QApplication(sys.argv) + self.path = join(dirname(__file__)) + self.homedir = self.getHomeDir() + + if platform in ("posix","linux2"): + configdir = join(self.homedir, ".pyload") + else: + configdir = join(self.homedir, "pyload") + + #chdir(configdir) + self.configdir = configdir + + try: + makedirs(self.configdir) + except: + pass + + self.init(True) + + def getHomeDir(self): + homedir = "" + + if platform == 'nt': + homedir = expanduser("~") + if homedir == "~": + import ctypes + CSIDL_APPDATA = 26 + _SHGetFolderPath = ctypes.windll.shell32.SHGetFolderPathW + _SHGetFolderPath.argtypes = [ctypes.wintypes.HWND, + ctypes.c_int, + ctypes.wintypes.HANDLE, + ctypes.wintypes.DWORD, ctypes.wintypes.LPCWSTR] + + path_buf = ctypes.wintypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) + result = _SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, path_buf) + homedir = path_buf.value + else: + homedir = expanduser("~") + return homedir + + def init(self, first=False): + """ + set main things up + """ + self.parser = XMLParser(join(self.configdir, "gui.xml"), join(self.path, "module", "config", "gui_default.xml")) + lang = self.parser.xml.elementsByTagName("language").item(0).toElement().text() + if not lang: + parser = XMLParser(join(self.path, "module", "config", "gui_default.xml")) + lang = parser.xml.elementsByTagName("language").item(0).toElement().text() + + translation = gettext.translation("pyLoadGui", join(self.path, "locale"), languages=[str(lang)]) + try: + translation.install(unicode=(True if sys.stdout.encoding.lower().startswith("utf") else False)) + except: + translation.install(unicode=False) + + self.connector = Connector() + self.mainWindow = MainWindow(self.connector) + self.connWindow = ConnectionManager() + self.mainloop = self.Loop(self) + self.connectSignals() + + self.checkClipboard = False + default = self.refreshConnections() + self.connData = None + self.captchaProcessing = False + + if first: + self.tray = TrayIcon() + self.tray.show() + self.notification = Notification(self.tray) + self.connect(self, SIGNAL("showMessage"), self.notification.showMessage) + self.connect(self.tray.exitAction, SIGNAL("triggered()"), self.app.quit) + self.connect(self.tray.showAction, SIGNAL("toggled(bool)"), self.mainWindow.setVisible) + self.connect(self.mainWindow, SIGNAL("hidden"), self.tray.mainWindowHidden) + + if not first: + self.connWindow.show() + else: + self.connWindow.edit.setData(default) + data = self.connWindow.edit.getData() + self.slotConnect(data) + + def startMain(self): + """ + start all refresh threads and show main window + """ + if not self.connector.canConnect(): + self.init() + return + self.connector.start() + self.connect(self.connector, SIGNAL("connectionLost"), sys.exit) + sleep(1) + self.restoreMainWindow() + self.mainWindow.show() + self.initQueue() + self.initPackageCollector() + self.mainloop.start() + self.clipboard = self.app.clipboard() + self.connect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) + self.mainWindow.actions["clipboard"].setChecked(self.checkClipboard) + + self.mainWindow.tabs["settings"]["w"].setConnector(self.connector) + self.mainWindow.tabs["settings"]["w"].loadConfig() + self.tray.showAction.setDisabled(False) + + def stopMain(self): + """ + stop all refresh threads and hide main window + """ + self.tray.showAction.setDisabled(True) + self.disconnect(self.clipboard, SIGNAL('dataChanged()'), self.slotClipboardChange) + self.disconnect(self.connector, SIGNAL("connectionLost"), sys.exit) + self.mainloop.stop() + self.connector.stop() + self.mainWindow.saveWindow() + self.mainWindow.hide() + self.queue.stop() + self.connector.wait() + + def connectSignals(self): + """ + signal and slot stuff, yay! + """ + self.connect(self.connector, SIGNAL("error_box"), self.slotErrorBox) + self.connect(self.connWindow, SIGNAL("saveConnection"), self.slotSaveConnection) + self.connect(self.connWindow, SIGNAL("removeConnection"), self.slotRemoveConnection) + self.connect(self.connWindow, SIGNAL("connect"), self.slotConnect) + self.connect(self.mainWindow, SIGNAL("connector"), self.slotShowConnector) + self.connect(self.mainWindow, SIGNAL("addPackage"), self.slotAddPackage) + self.connect(self.mainWindow, SIGNAL("setDownloadStatus"), self.slotSetDownloadStatus) + self.connect(self.mainWindow, SIGNAL("saveMainWindow"), self.slotSaveMainWindow) + self.connect(self.mainWindow, SIGNAL("pushPackageToQueue"), self.slotPushPackageToQueue) + self.connect(self.mainWindow, SIGNAL("restartDownload"), self.slotRestartDownload) + self.connect(self.mainWindow, SIGNAL("removeDownload"), self.slotRemoveDownload) + self.connect(self.mainWindow, SIGNAL("abortDownload"), self.slotAbortDownload) + self.connect(self.mainWindow, SIGNAL("addContainer"), self.slotAddContainer) + self.connect(self.mainWindow, SIGNAL("stopAllDownloads"), self.slotStopAllDownloads) + self.connect(self.mainWindow, SIGNAL("setClipboardStatus"), self.slotSetClipboardStatus) + self.connect(self.mainWindow, SIGNAL("changePackageName"), self.slotChangePackageName) + self.connect(self.mainWindow, SIGNAL("pullOutPackage"), self.slotPullOutPackage) + self.connect(self.mainWindow, SIGNAL("setPriority"), self.slotSetPriority) + self.connect(self.mainWindow, SIGNAL("reloadAccounts"), self.slotReloadAccounts) + + self.connect(self.mainWindow, SIGNAL("quit"), self.quit) + self.connect(self.mainWindow.captchaDock, SIGNAL("done"), self.slotCaptchaDone) + + def slotShowConnector(self): + """ + emitted from main window (menu) + hide the main window and show connection manager + (to switch to other core) + """ + self.stopMain() + self.init() + + def quit(self): + """ + quit gui + """ + self.app.quit() + + def loop(self): + """ + start application loop + """ + sys.exit(self.app.exec_()) + + def slotErrorBox(self, msg): + """ + display a nice error box + """ + msgb = QMessageBox(QMessageBox.Warning, "Error", msg) + msgb.exec_() + + def initPackageCollector(self): + """ + init the package collector view + * columns + * selection + * refresh thread + * drag'n'drop + """ + view = self.mainWindow.tabs["collector"]["package_view"] + view.setSelectionBehavior(QAbstractItemView.SelectRows) + view.setSelectionMode(QAbstractItemView.ExtendedSelection) + def dropEvent(klass, event): + event.setDropAction(Qt.CopyAction) + event.accept() + view = event.source() + if view == klass: + items = view.selectedItems() + for item in items: + if not hasattr(item.parent(), "getPackData"): + continue + target = view.itemAt(event.pos()) + if not hasattr(target, "getPackData"): + target = target.parent() + klass.emit(SIGNAL("droppedToPack"), target.getPackData()["id"], item.getFileData()["id"]) + event.ignore() + return + items = view.selectedItems() + for item in items: + row = view.indexOfTopLevelItem(item) + view.takeTopLevelItem(row) + def dragEvent(klass, event): + view = event.source() + #dragOkay = False + #items = view.selectedItems() + #for item in items: + # if hasattr(item, "_data"): + # if item._data["id"] == "fixed" or item.parent()._data["id"] == "fixed": + # dragOkay = True + # else: + # dragOkay = True + #if dragOkay: + event.accept() + #else: + # event.ignore() + view.dropEvent = dropEvent + view.dragEnterEvent = dragEvent + view.setDragEnabled(True) + view.setDragDropMode(QAbstractItemView.DragDrop) + view.setDropIndicatorShown(True) + view.setDragDropOverwriteMode(True) + view.connect(view, SIGNAL("droppedToPack"), self.slotAddFileToPackage) + #self.packageCollector = PackageCollector(view, self.connector) + self.packageCollector = view.model() + + def initQueue(self): + """ + init the queue view + * columns + * progressbar + """ + view = self.mainWindow.tabs["queue"]["view"] + view.setSelectionBehavior(QAbstractItemView.SelectRows) + view.setSelectionMode(QAbstractItemView.ExtendedSelection) + self.queue = view.model() + self.queue.start() + + def refreshServerStatus(self): + """ + refresh server status and overall speed in the status bar + """ + status = self.connector.getServerStatus() + if status["pause"]: + status["status"] = _("Paused") + else: + status["status"] = _("Running") + status["speed"] = int(status["speed"]) + text = _("Status: %(status)s | Speed: %(speed)s kb/s") % status + self.mainWindow.actions["toggle_status"].setChecked(not status["pause"]) + self.mainWindow.serverStatus.setText(text) + + def refreshLog(self): + """ + update log window + """ + offset = self.mainWindow.tabs["log"]["text"].logOffset + lines = self.connector.getLog(offset) + if not lines: + return + self.mainWindow.tabs["log"]["text"].logOffset += len(lines) + for line in lines: + self.mainWindow.tabs["log"]["text"].emit(SIGNAL("append(QString)"), line.strip("\n")) + cursor = self.mainWindow.tabs["log"]["text"].textCursor() + cursor.movePosition(QTextCursor.End, QTextCursor.MoveAnchor) + self.mainWindow.tabs["log"]["text"].setTextCursor(cursor) + + def getConnections(self): + """ + parse all connections in the config file + """ + connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) + if connectionsNode.isNull(): + raise Exception("null") + connections = self.parser.parseNode(connectionsNode) + ret = [] + for conn in connections: + data = {} + data["type"] = conn.attribute("type", "remote") + data["default"] = conn.attribute("default", "False") + data["id"] = conn.attribute("id", uuid().hex) + if data["default"] == "True": + data["default"] = True + else: + data["default"] = False + subs = self.parser.parseNode(conn, "dict") + if not subs.has_key("name"): + data["name"] = _("Unnamed") + else: + data["name"] = subs["name"].text() + if data["type"] == "remote": + if not subs.has_key("server"): + continue + else: + data["host"] = subs["server"].text() + data["ssl"] = subs["server"].attribute("ssl", "False") + if data["ssl"] == "True": + data["ssl"] = True + else: + data["ssl"] = False + data["user"] = subs["server"].attribute("user", "admin") + data["port"] = int(subs["server"].attribute("port", "7227")) + data["password"] = subs["server"].attribute("password", "") + ret.append(data) + return ret + + def slotSaveConnection(self, data): + """ + save connection to config file + """ + connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) + if connectionsNode.isNull(): + raise Exception("null") + connections = self.parser.parseNode(connectionsNode) + connNode = self.parser.xml.createElement("connection") + connNode.setAttribute("default", str(data["default"])) + connNode.setAttribute("type", data["type"]) + connNode.setAttribute("id", data["id"]) + nameNode = self.parser.xml.createElement("name") + nameText = self.parser.xml.createTextNode(data["name"]) + nameNode.appendChild(nameText) + connNode.appendChild(nameNode) + if data["type"] == "remote": + serverNode = self.parser.xml.createElement("server") + serverNode.setAttribute("ssl", data["ssl"]) + serverNode.setAttribute("user", data["user"]) + serverNode.setAttribute("port", data["port"]) + serverNode.setAttribute("password", data["password"]) + hostText = self.parser.xml.createTextNode(data["host"]) + serverNode.appendChild(hostText) + connNode.appendChild(serverNode) + found = False + for c in connections: + cid = c.attribute("id", "None") + if str(cid) == str(data["id"]): + found = c + break + if found: + connectionsNode.replaceChild(connNode, found) + else: + connectionsNode.appendChild(connNode) + self.parser.saveData() + self.refreshConnections() + + def slotRemoveConnection(self, data): + """ + remove connection from config file + """ + connectionsNode = self.parser.xml.elementsByTagName("connections").item(0) + if connectionsNode.isNull(): + raise Exception("null") + connections = self.parser.parseNode(connectionsNode) + found = False + for c in connections: + cid = c.attribute("id", "None") + if str(cid) == str(data["id"]): + found = c + break + if found: + connectionsNode.removeChild(found) + self.parser.saveData() + self.refreshConnections() + + def slotConnect(self, data): + """ + connect to a core + if connection is local, parse the core config file for data + set up connector, show main window + """ + self.connWindow.hide() + if not data["type"] == "remote": + + coreparser = ConfigParser(self.configdir) + if not coreparser.config: + raise Exception + #except: + # data["port"] = 7227 + # data["user"] = "admin" + # data["password"] = "pwhere" + # data["host"] = "127.0.0.1" + # data["ssl"] = False + + data["port"] = coreparser.get("remote","port") + data["user"] = coreparser.get("remote","username") + data["password"] = coreparser.get("remote","password") + data["host"] = "127.0.0.1" + data["ssl"] = coreparser.get("ssl","activated") + data["ssl"] = "s" if data["ssl"] else "" + server_url = "http%(ssl)s://%(user)s:%(password)s@%(host)s:%(port)s/" % data + self.connector.setAddr(str(server_url)) + self.startMain() + + def refreshConnections(self): + """ + reload connetions and display them + """ + self.parser.loadData() + conns = self.getConnections() + self.connWindow.emit(SIGNAL("setConnections"), conns) + for conn in conns: + if conn["default"]: + return conn + return None + + def slotSetDownloadStatus(self, status): + """ + toolbar start/pause slot + """ + self.connector.setPause(not status) + + def slotAddPackage(self, name, links): + """ + emitted from main window + add package to the collector + """ + self.connector.proxy.add_package(name, links) + + def slotAddFileToPackage(self, pid, fid): + """ + emitted from collector view after a drop action + """ + self.connector.addFileToPackage(fid, pid) + + def slotAddContainer(self, path): + """ + emitted from main window + add container + """ + filename = basename(path) + type = "".join(filename.split(".")[-1]) + fh = open(path, "r") + content = fh.read() + fh.close() + self.connector.proxy.upload_container(filename, Binary(content)) + + def slotSaveMainWindow(self, state, geo): + """ + save the window geometry and toolbar/dock position to config file + """ + mainWindowNode = self.parser.xml.elementsByTagName("mainWindow").item(0) + if mainWindowNode.isNull(): + mainWindowNode = self.parser.xml.createElement("mainWindow") + self.parser.root.appendChild(mainWindowNode) + stateNode = mainWindowNode.toElement().elementsByTagName("state").item(0) + geoNode = mainWindowNode.toElement().elementsByTagName("geometry").item(0) + newStateNode = self.parser.xml.createTextNode(state) + newGeoNode = self.parser.xml.createTextNode(geo) + + stateNode.removeChild(stateNode.firstChild()) + geoNode.removeChild(geoNode.firstChild()) + stateNode.appendChild(newStateNode) + geoNode.appendChild(newGeoNode) + + self.parser.saveData() + + def restoreMainWindow(self): + """ + load and restore main window geometry and toolbar/dock position from config + """ + mainWindowNode = self.parser.xml.elementsByTagName("mainWindow").item(0) + if mainWindowNode.isNull(): + return + nodes = self.parser.parseNode(mainWindowNode, "dict") + + state = str(nodes["state"].text()) + geo = str(nodes["geometry"].text()) + + self.mainWindow.restoreWindow(state, geo) + self.mainWindow.captchaDock.hide() + + def slotPushPackageToQueue(self, id): + """ + emitted from main window + push the collector package to queue + """ + self.connector.proxy.push_package_to_queue(id) + + def slotRestartDownload(self, id, isPack): + """ + emitted from main window + restart download + """ + if isPack: + self.connector.restartPackage(id) + else: + self.connector.restartFile(id) + + def slotRemoveDownload(self, id, isPack): + """ + emitted from main window + remove download + """ + if isPack: + self.connector.removePackage(id) + else: + self.connector.removeFile(id) + + def slotAbortDownload(self, id, isPack): + """ + emitted from main window + remove download + """ + if isPack: + data = self.connector.proxy.get_package_data(id) + self.connector.proxy.abort_files(data["links"].keys()) + else: + self.connector.proxy.abort_files([id]) + + def slotStopAllDownloads(self): + """ + emitted from main window + stop all running downloads + """ + self.connector.stopAllDownloads() + + def slotClipboardChange(self): + """ + called if clipboard changes + """ + if self.checkClipboard: + text = self.clipboard.text() + pattern = re.compile(r"(http|https)://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?/.*)?") + matches = pattern.finditer(text) + for match in matches: + self.slotAddLinks([str(match.group(0))]) + + def slotSetClipboardStatus(self, status): + """ + set clipboard checking + """ + self.checkClipboard = status + + def slotChangePackageName(self, pid, name): + """ + package name edit finished + """ + self.connector.setPackageName(pid, str(name)) + + def slotPullOutPackage(self, pid): + """ + pull package out of the queue + """ + self.connector.proxy.pull_out_package(pid) + + def slotSetPriority(self, pid, level): + """ + set package priority + """ + self.connector.proxy.set_priority(pid, level) + + def checkCaptcha(self): + if self.connector.captchaWaiting() and self.mainWindow.captchaDock.isFree(): + cid, img, imgType = self.connector.getCaptcha() + self.mainWindow.captchaDock.emit(SIGNAL("setTask"), cid, str(img), imgType) + self.mainWindow.show() + elif not self.mainWindow.captchaDock.isFree(): + status = self.connector.getCaptchaStatus(self.mainWindow.captchaDock.currentID) + if not (status == "user" or status == "shared-user"): + self.mainWindow.captchaDock.hide() + self.mainWindow.captchaDock.processing = False + self.mainWindow.captchaDock.currentID = None + + def slotCaptchaDone(self, cid, result): + self.connector.setCaptchaResult(str(cid), str(result)) + + def pullEvents(self): + events = self.connector.getEvents() + for event in events: + if event[1] == "queue": + self.queue.addEvent(event) + try: + if event[0] == "update" and event[2] == "file": + info = self.connector.getLinkInfo(event[3]) + if info["status_type"] == "finished": + self.emit(SIGNAL("showMessage"), _("Finished downloading of '%s'") % info["status_filename"]) + elif info["status_type"] == "downloading": + self.emit(SIGNAL("showMessage"), _("Started downloading '%s'") % info["status_filename"]) + elif info["status_type"] == "failed": + self.emit(SIGNAL("showMessage"), _("Failed downloading '%s'!") % info["status_filename"]) + if event[0] == "insert" and event[2] == "file": + info = self.connector.getLinkInfo(event[3]) + self.emit(SIGNAL("showMessage"), _("Added '%s' to queue") % info["status_filename"]) + except: + pass + elif event[1] == "collector": + self.packageCollector.addEvent(event) + + def slotReloadAccounts(self): + self.mainWindow.tabs["accounts"]["view"].model().reloadData() + + class Loop(): + def __init__(self, parent): + self.parent = parent + self.timer = QTimer() + self.timer.connect(self.timer, SIGNAL("timeout()"), self.update) + + def start(self): + self.update() + self.timer.start(1000) + + def update(self): + """ + methods to call + """ + self.parent.refreshServerStatus() + self.parent.refreshLog() + self.parent.checkCaptcha() + self.parent.pullEvents() + + def stop(self): + self.timer.stop() + + +class TrayIcon(QSystemTrayIcon): + def __init__(self): + QSystemTrayIcon.__init__(self, QIcon(join("icons", "logo.png"))) + self.contextMenu = QMenu() + self.showAction = QAction(_("Show"), self.contextMenu) + self.showAction.setCheckable(True) + self.showAction.setChecked(True) + self.showAction.setDisabled(True) + self.contextMenu.addAction(self.showAction) + self.exitAction = QAction(QIcon(join("icons", "close.png")), _("Exit"), self.contextMenu) + self.contextMenu.addAction(self.exitAction) + self.setContextMenu(self.contextMenu) + + self.connect(self, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.doubleClicked) + + def mainWindowHidden(self): + self.showAction.setChecked(False) + + def doubleClicked(self, reason): + if self.showAction.isEnabled(): + if reason == QSystemTrayIcon.DoubleClick: + self.showAction.toggle() + +class Notification(QObject): + def __init__(self, tray): + QObject.__init__(self) + self.tray = tray + self.usePynotify = False + + try: + self.usePynotify = pynotify.init("icon-summary-body") + except: + pass + + def showMessage(self, body): + if self.usePynotify: + n = pynotify.Notification("pyload", body, join("icons", "logo.png")) + try: + n.set_hint_string("x-canonical-append", "") + except: + pass + n.show() + else: + self.tray.showMessage("pyload", body) + +if __name__ == "__main__": + app = main() + app.loop() + |