diff options
author | Walter Purcaro <vuolter@gmail.com> | 2014-06-28 14:49:34 +0200 |
---|---|---|
committer | Walter Purcaro <vuolter@gmail.com> | 2014-06-28 20:21:03 +0200 |
commit | 6abc3221c9b5ba1a1b54633c8283c7c5c978558a (patch) | |
tree | b98bb58c4e10bc6638cebfc2fb1327ca71adb797 | |
parent | Update CherryPy wsgiserver to version 3.2.1 (diff) | |
download | pyload-6abc3221c9b5ba1a1b54633c8283c7c5c978558a.tar.xz |
[GUI] Removed
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | docs/docs.conf | 4 | ||||
-rw-r--r-- | icons/abort.png | bin | 2569 -> 0 bytes | |||
-rw-r--r-- | icons/add_small.png | bin | 3356 -> 0 bytes | |||
-rw-r--r-- | icons/clipboard.png | bin | 1344 -> 0 bytes | |||
-rw-r--r-- | icons/close.png | bin | 2569 -> 0 bytes | |||
-rw-r--r-- | icons/edit_small.png | bin | 570 -> 0 bytes | |||
-rw-r--r-- | icons/logo-gui.png | bin | 8093 -> 0 bytes | |||
-rw-r--r-- | icons/logo.png | bin | 8172 -> 0 bytes | |||
-rw-r--r-- | icons/pull_small.png | bin | 614 -> 0 bytes | |||
-rw-r--r-- | icons/push_small.png | bin | 618 -> 0 bytes | |||
-rw-r--r-- | icons/pyload-gui.ico | bin | 51122 -> 0 bytes | |||
-rw-r--r-- | icons/pyload.ico | bin | 7206 -> 0 bytes | |||
-rw-r--r-- | icons/refresh1_small.png | bin | 3474 -> 0 bytes | |||
-rw-r--r-- | icons/refresh_small.png | bin | 821 -> 0 bytes | |||
-rw-r--r-- | icons/remove_small.png | bin | 287 -> 0 bytes | |||
-rw-r--r-- | icons/toolbar_add.png | bin | 932 -> 0 bytes | |||
-rw-r--r-- | icons/toolbar_pause.png | bin | 943 -> 0 bytes | |||
-rw-r--r-- | icons/toolbar_remove.png | bin | 496 -> 0 bytes | |||
-rw-r--r-- | icons/toolbar_start.png | bin | 1504 -> 0 bytes | |||
-rw-r--r-- | icons/toolbar_stop.png | bin | 523 -> 0 bytes | |||
-rw-r--r-- | locale/crowdin.yaml | 3 | ||||
-rw-r--r-- | locale/gui.pot | 511 | ||||
-rw-r--r-- | module/Api.py | 6 | ||||
-rw-r--r-- | module/config/gui_default.xml | 13 | ||||
-rw-r--r-- | module/gui/AccountEdit.py | 104 | ||||
-rw-r--r-- | module/gui/Accounts.py | 212 | ||||
-rw-r--r-- | module/gui/CNLServer.py | 226 | ||||
-rw-r--r-- | module/gui/CaptchaDock.py | 93 | ||||
-rw-r--r-- | module/gui/Collector.py | 406 | ||||
-rw-r--r-- | module/gui/ConnectionManager.py | 301 | ||||
-rw-r--r-- | module/gui/CoreConfigParser.py | 162 | ||||
-rw-r--r-- | module/gui/LinkDock.py | 56 | ||||
-rw-r--r-- | module/gui/MainWindow.py | 697 | ||||
-rw-r--r-- | module/gui/Overview.py | 197 | ||||
-rw-r--r-- | module/gui/PackageDock.py | 90 | ||||
-rw-r--r-- | module/gui/Queue.py | 389 | ||||
-rw-r--r-- | module/gui/SettingsWidget.py | 202 | ||||
-rw-r--r-- | module/gui/XMLParser.py | 71 | ||||
-rw-r--r-- | module/gui/__init__.py | 1 | ||||
-rw-r--r-- | module/gui/connector.py | 165 | ||||
-rw-r--r-- | module/setup.py | 31 | ||||
-rw-r--r-- | pavement.py | 3 | ||||
-rwxr-xr-x | pyLoadCore.py | 1 | ||||
-rwxr-xr-x | pyLoadGui.py | 764 | ||||
-rw-r--r-- | pyload.ico (renamed from icons/pyload2.ico) | bin | 9662 -> 9662 bytes | |||
-rw-r--r-- | systemCheck.py | 22 |
48 files changed, 19 insertions, 4715 deletions
diff --git a/.gitignore b/.gitignore index c78dbc04a..b94b19812 100644 --- a/.gitignore +++ b/.gitignore @@ -76,10 +76,8 @@ ssl.key *_links.txt links.txt module/config/core.xml -module/config/gui.xml module/config/plugin.xml module/web/pyload.db #pyload/config/core.xml -#pyload/config/gui.xml #pyload/config/plugin.xml #pyload/web/pyload.db diff --git a/docs/conf.py b/docs/conf.py index a682f7127..6f97f527e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -133,7 +133,7 @@ html_logo = join(dir_name, "module", "web", "media", "default", "img", "pyload-l # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -html_favicon = join(dir_name, "icons", "pyload2.ico") +html_favicon = join(dir_name, "pyload.ico") # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/docs/docs.conf b/docs/docs.conf index e197cfa43..57fda5930 100644 --- a/docs/docs.conf +++ b/docs/docs.conf @@ -3,12 +3,12 @@ [epydoc] -modules: pyLoadCore.py, pyLoadCli.py, pyloadGui.py, module +modules: pyLoadCore.py, pyLoadCli.py, module output: html target: docs docformat: restructuredtext -exclude: module\.lib|module\.remote\.thriftbackend\.thriftgen|PyQt4|\.pyc|\.pyo|module\.plugins\.(accounts|captcha|container|crypter|hooks|hoster) +exclude: module\.lib|module\.remote\.thriftbackend\.thriftgen|\.pyc|\.pyo|module\.plugins\.(accounts|captcha|container|crypter|hooks|hoster) name: pyLoad Documentation url: http://docs.pyload.org diff --git a/icons/abort.png b/icons/abort.png Binary files differdeleted file mode 100644 index 66170aae7..000000000 --- a/icons/abort.png +++ /dev/null diff --git a/icons/add_small.png b/icons/add_small.png Binary files differdeleted file mode 100644 index 4dc88b09b..000000000 --- a/icons/add_small.png +++ /dev/null diff --git a/icons/clipboard.png b/icons/clipboard.png Binary files differdeleted file mode 100644 index 9ba608eba..000000000 --- a/icons/clipboard.png +++ /dev/null diff --git a/icons/close.png b/icons/close.png Binary files differdeleted file mode 100644 index 66170aae7..000000000 --- a/icons/close.png +++ /dev/null diff --git a/icons/edit_small.png b/icons/edit_small.png Binary files differdeleted file mode 100644 index eb76e21b4..000000000 --- a/icons/edit_small.png +++ /dev/null diff --git a/icons/logo-gui.png b/icons/logo-gui.png Binary files differdeleted file mode 100644 index 5994b274d..000000000 --- a/icons/logo-gui.png +++ /dev/null diff --git a/icons/logo.png b/icons/logo.png Binary files differdeleted file mode 100644 index 72a95b740..000000000 --- a/icons/logo.png +++ /dev/null diff --git a/icons/pull_small.png b/icons/pull_small.png Binary files differdeleted file mode 100644 index 432ad321f..000000000 --- a/icons/pull_small.png +++ /dev/null diff --git a/icons/push_small.png b/icons/push_small.png Binary files differdeleted file mode 100644 index 701fc69e3..000000000 --- a/icons/push_small.png +++ /dev/null diff --git a/icons/pyload-gui.ico b/icons/pyload-gui.ico Binary files differdeleted file mode 100644 index 00a1a53ff..000000000 --- a/icons/pyload-gui.ico +++ /dev/null diff --git a/icons/pyload.ico b/icons/pyload.ico Binary files differdeleted file mode 100644 index 58b1f4b89..000000000 --- a/icons/pyload.ico +++ /dev/null diff --git a/icons/refresh1_small.png b/icons/refresh1_small.png Binary files differdeleted file mode 100644 index ce4f24efc..000000000 --- a/icons/refresh1_small.png +++ /dev/null diff --git a/icons/refresh_small.png b/icons/refresh_small.png Binary files differdeleted file mode 100644 index 1ffd18d97..000000000 --- a/icons/refresh_small.png +++ /dev/null diff --git a/icons/remove_small.png b/icons/remove_small.png Binary files differdeleted file mode 100644 index bf99763e8..000000000 --- a/icons/remove_small.png +++ /dev/null diff --git a/icons/toolbar_add.png b/icons/toolbar_add.png Binary files differdeleted file mode 100644 index 17003e9f0..000000000 --- a/icons/toolbar_add.png +++ /dev/null diff --git a/icons/toolbar_pause.png b/icons/toolbar_pause.png Binary files differdeleted file mode 100644 index b7a727b71..000000000 --- a/icons/toolbar_pause.png +++ /dev/null diff --git a/icons/toolbar_remove.png b/icons/toolbar_remove.png Binary files differdeleted file mode 100644 index 1e9c00e16..000000000 --- a/icons/toolbar_remove.png +++ /dev/null diff --git a/icons/toolbar_start.png b/icons/toolbar_start.png Binary files differdeleted file mode 100644 index 1123266e6..000000000 --- a/icons/toolbar_start.png +++ /dev/null diff --git a/icons/toolbar_stop.png b/icons/toolbar_stop.png Binary files differdeleted file mode 100644 index b388e3d72..000000000 --- a/icons/toolbar_stop.png +++ /dev/null diff --git a/locale/crowdin.yaml b/locale/crowdin.yaml index cc3595238..96898d500 100644 --- a/locale/crowdin.yaml +++ b/locale/crowdin.yaml @@ -13,6 +13,3 @@ files: - source: 'pyLoad/core.pot' translation: 'pyLoad/%two_letters_code%/LC_MESSAGES/pyLoad.po' - - - source: 'pyLoad/gui.pot' - translation: 'pyLoad/%two_letters_code%/LC_MESSAGES/pyLoadGui.po' diff --git a/locale/gui.pot b/locale/gui.pot deleted file mode 100644 index aea17ad28..000000000 --- a/locale/gui.pot +++ /dev/null @@ -1,511 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR pyLoad Team -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: pyLoad 0.4.9\n" -"Report-Msgid-Bugs-To: 'bugs@pyload.org'\n" -"POT-Creation-Date: 2014-04-08 15:01+0200\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" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: pyLoadGui.py:290 -msgid "paused" -msgstr "" - -#: pyLoadGui.py:292 -msgid "running" -msgstr "" - -#: pyLoadGui.py:332 -msgid "Unnamed" -msgstr "" - -#: pyLoadGui.py:655 -#, python-format -msgid "Finished downloading of '%s'" -msgstr "" - -#: pyLoadGui.py:657 -#, python-format -msgid "Failed downloading '%s'!" -msgstr "" - -#: pyLoadGui.py:660 -#, python-format -msgid "Added '%s' to queue" -msgstr "" - -#: pyLoadGui.py:685 -msgid "Connection lost" -msgstr "" - -#: pyLoadGui.py:685 -msgid "Lost connection to the core!" -msgstr "" - -#: pyLoadGui.py:720 -msgid "Show" -msgstr "" - -#: pyLoadGui.py:725 module/gui/MainWindow.py:133 -msgid "Exit" -msgstr "" - -#: module/gui/MainWindow.py:44 -msgid "pyLoad Client" -msgstr "" - -#: module/gui/MainWindow.py:92 -msgid "Packages:" -msgstr "" - -#: module/gui/MainWindow.py:96 -msgid "Files:" -msgstr "" - -#: module/gui/MainWindow.py:100 -msgid "Status:" -msgstr "" - -#: module/gui/MainWindow.py:104 -msgid "Space:" -msgstr "" - -#: module/gui/MainWindow.py:108 -msgid "Speed:" -msgstr "" - -#: module/gui/MainWindow.py:129 -msgid "File" -msgstr "" - -#: module/gui/MainWindow.py:130 -msgid "Connections" -msgstr "" - -#: module/gui/MainWindow.py:134 -msgid "Connection manager" -msgstr "" - -#: module/gui/MainWindow.py:156 -msgid "Overview" -msgstr "" - -#: module/gui/MainWindow.py:157 -msgid "Queue" -msgstr "" - -#: module/gui/MainWindow.py:158 -msgid "Collector" -msgstr "" - -#: module/gui/MainWindow.py:159 -msgid "Accounts" -msgstr "" - -#: module/gui/MainWindow.py:160 -msgid "Settings" -msgstr "" - -#: module/gui/MainWindow.py:161 -msgid "Log" -msgstr "" - -#: module/gui/MainWindow.py:190 -msgid "Hide Toolbar" -msgstr "" - -#: module/gui/MainWindow.py:194 -msgid "Toggle Pause/Resume" -msgstr "" - -#: module/gui/MainWindow.py:200 -msgid "Stop" -msgstr "" - -#: module/gui/MainWindow.py:202 module/gui/MainWindow.py:302 -#: module/gui/MainWindow.py:322 -msgid "Add" -msgstr "" - -#: module/gui/MainWindow.py:204 -msgid "Check Clipboard" -msgstr "" - -#: module/gui/MainWindow.py:211 module/gui/MainWindow.py:308 -#: module/gui/Overview.py:101 -msgid "Package" -msgstr "" - -#: module/gui/MainWindow.py:212 module/gui/MainWindow.py:309 -msgid "Container" -msgstr "" - -#: module/gui/MainWindow.py:213 -msgid "Account" -msgstr "" - -#: module/gui/MainWindow.py:214 module/gui/MainWindow.py:310 -msgid "Links" -msgstr "" - -#: module/gui/MainWindow.py:238 -msgid "Push selected packages to queue" -msgstr "" - -#: module/gui/MainWindow.py:261 -msgid "New Account" -msgstr "" - -#: module/gui/MainWindow.py:275 module/gui/MainWindow.py:295 -#: module/gui/MainWindow.py:323 module/gui/ConnectionManager.py:49 -msgid "Remove" -msgstr "" - -#: module/gui/MainWindow.py:276 module/gui/MainWindow.py:298 -msgid "Restart" -msgstr "" - -#: module/gui/MainWindow.py:277 -msgid "Pull out" -msgstr "" - -#: module/gui/MainWindow.py:278 -msgid "Abort" -msgstr "" - -#: module/gui/MainWindow.py:279 module/gui/MainWindow.py:297 -msgid "Edit Name" -msgstr "" - -#: module/gui/MainWindow.py:296 -msgid "Push to queue" -msgstr "" - -#: module/gui/MainWindow.py:299 -msgid "Refresh Status" -msgstr "" - -#: module/gui/MainWindow.py:324 module/gui/ConnectionManager.py:48 -msgid "Edit" -msgstr "" - -#: module/gui/MainWindow.py:402 -#, python-format -msgid "All Container Types (%s)" -msgstr "" - -#: module/gui/MainWindow.py:403 -#, python-format -msgid "DLC (%s)" -msgstr "" - -#: module/gui/MainWindow.py:404 -#, python-format -msgid "CCF (%s)" -msgstr "" - -#: module/gui/MainWindow.py:405 -#, python-format -msgid "RSDF (%s)" -msgstr "" - -#: module/gui/MainWindow.py:406 -#, python-format -msgid "Text Files (%s)" -msgstr "" - -#: module/gui/MainWindow.py:408 -msgid "Open container" -msgstr "" - -#: module/gui/Collector.py:47 -msgid "finished" -msgstr "" - -#: module/gui/Collector.py:48 -msgid "offline" -msgstr "" - -#: module/gui/Collector.py:49 -msgid "online" -msgstr "" - -#: module/gui/Collector.py:50 -msgid "queued" -msgstr "" - -#: module/gui/Collector.py:51 -msgid "skipped" -msgstr "" - -#: module/gui/Collector.py:52 -msgid "waiting" -msgstr "" - -#: module/gui/Collector.py:53 -msgid "temp. offline" -msgstr "" - -#: module/gui/Collector.py:54 -msgid "starting" -msgstr "" - -#: module/gui/Collector.py:55 -msgid "failed" -msgstr "" - -#: module/gui/Collector.py:56 -msgid "aborted" -msgstr "" - -#: module/gui/Collector.py:57 -msgid "decrypting" -msgstr "" - -#: module/gui/Collector.py:58 -msgid "custom" -msgstr "" - -#: module/gui/Collector.py:59 -msgid "downloading" -msgstr "" - -#: module/gui/Collector.py:60 -msgid "processing" -msgstr "" - -#: module/gui/Collector.py:284 module/gui/PackageDock.py:66 -#: module/gui/Queue.py:152 -msgid "Name" -msgstr "" - -#: module/gui/Collector.py:286 module/gui/Queue.py:156 -msgid "Plugin" -msgstr "" - -#: module/gui/Collector.py:288 module/gui/Queue.py:154 -msgid "Status" -msgstr "" - -#: module/gui/Collector.py:290 module/gui/Queue.py:158 -msgid "Size" -msgstr "" - -#: module/gui/connector.py:76 -msgid "bad login credentials" -msgstr "" - -#: module/gui/connector.py:78 -msgid "no ssl support" -msgstr "" - -#: module/gui/connector.py:80 -msgid "can't connect to host" -msgstr "" - -#: module/gui/connector.py:94 -#, python-format -msgid "server is version %(new)s client accepts version %(current)s" -msgstr "" - -#: module/gui/SettingsWidget.py:74 -msgid "General" -msgstr "" - -#: module/gui/SettingsWidget.py:75 -msgid "Plugins" -msgstr "" - -#: module/gui/SettingsWidget.py:89 -msgid "Reload" -msgstr "" - -#: module/gui/SettingsWidget.py:90 module/gui/AccountEdit.py:53 -#: module/gui/ConnectionManager.py:206 -msgid "Save" -msgstr "" - -#: module/gui/SettingsWidget.py:192 -msgid "Yes" -msgstr "" - -#: module/gui/SettingsWidget.py:193 -msgid "No" -msgstr "" - -#: module/gui/PackageDock.py:25 -msgid "New Package" -msgstr "" - -#: module/gui/PackageDock.py:68 -msgid "Password" -msgstr "" - -#: module/gui/PackageDock.py:71 -msgid "Links in this Package" -msgstr "" - -#: module/gui/PackageDock.py:77 -msgid "Create" -msgstr "" - -#: module/gui/PackageDock.py:78 -msgid "Filter URLs" -msgstr "" - -#: module/gui/CaptchaDock.py:29 -msgid "Captcha" -msgstr "" - -#: module/gui/CaptchaDock.py:64 -msgid "OK" -msgstr "" - -#: module/gui/CaptchaDock.py:65 module/gui/ConnectionManager.py:207 -msgid "Cancel" -msgstr "" - -#: module/gui/Accounts.py:75 -msgid "not valid" -msgstr "" - -#: module/gui/Accounts.py:77 module/gui/Accounts.py:207 -msgid "n/a" -msgstr "" - -#: module/gui/Accounts.py:80 -msgid "%a, %d %b %Y %H:%M" -msgstr "" - -#: module/gui/Accounts.py:83 module/gui/Accounts.py:205 -msgid "unlimited" -msgstr "" - -#: module/gui/Accounts.py:138 module/gui/AccountEdit.py:38 -msgid "Type" -msgstr "" - -#: module/gui/Accounts.py:140 module/gui/AccountEdit.py:39 -msgid "Login" -msgstr "" - -#: module/gui/Accounts.py:142 -msgid "Valid until" -msgstr "" - -#: module/gui/Accounts.py:144 -msgid "Traffic left" -msgstr "" - -#: module/gui/Overview.py:71 module/gui/Overview.py:152 -msgid "Downloading" -msgstr "" - -#: module/gui/Overview.py:83 -msgid "Queued" -msgstr "" - -#: module/gui/Overview.py:147 -msgid "ETA: " -msgstr "" - -#: module/gui/Overview.py:149 -msgid "Parts: " -msgstr "" - -#: module/gui/Overview.py:151 -msgid "Finished" -msgstr "" - -#: module/gui/Overview.py:155 -#, python-format -msgid "Speed: %s" -msgstr "" - -#: module/gui/Overview.py:158 module/gui/Overview.py:160 -msgid "Size:" -msgstr "" - -#: module/gui/AccountEdit.py:32 -msgid "Edit account" -msgstr "" - -#: module/gui/AccountEdit.py:40 -msgid "New password" -msgstr "" - -#: module/gui/AccountEdit.py:83 -msgid "Create account" -msgstr "" - -#: module/gui/Queue.py:160 -msgid "ETA" -msgstr "" - -#: module/gui/Queue.py:162 -msgid "Progress" -msgstr "" - -#: module/gui/Queue.py:384 -#, python-format -msgid "waiting %d seconds" -msgstr "" - -#: module/gui/ConnectionManager.py:42 module/gui/ConnectionManager.py:185 -msgid "pyLoad ConnectionManager" -msgstr "" - -#: module/gui/ConnectionManager.py:47 -msgid "New" -msgstr "" - -#: module/gui/ConnectionManager.py:50 -msgid "Connect" -msgstr "" - -#: module/gui/ConnectionManager.py:56 -msgid "Connect:" -msgstr "" - -#: module/gui/ConnectionManager.py:73 -msgid "Use internal Core:" -msgstr "" - -#: module/gui/ConnectionManager.py:117 -#, python-format -msgid "%s (Default)" -msgstr "" - -#: module/gui/ConnectionManager.py:190 -msgid "Name:" -msgstr "" - -#: module/gui/ConnectionManager.py:191 -msgid "Host:" -msgstr "" - -#: module/gui/ConnectionManager.py:192 -msgid "Local:" -msgstr "" - -#: module/gui/ConnectionManager.py:193 -msgid "User:" -msgstr "" - -#: module/gui/ConnectionManager.py:194 -msgid "Password:" -msgstr "" - -#: module/gui/ConnectionManager.py:195 -msgid "Port:" -msgstr "" diff --git a/module/Api.py b/module/Api.py index 348d9c8ee..ad11105ba 100644 --- a/module/Api.py +++ b/module/Api.py @@ -923,10 +923,8 @@ class Api(Iface): """ if self.core.config["remote"]["nolocalauth"] and remoteip == "127.0.0.1": return "local" - if self.core.startedInGui and remoteip == "127.0.0.1": - return "local" - - return self.core.db.checkAuth(username, password) + else: + return self.core.db.checkAuth(username, password) def isAuthorized(self, func, userdata): """checks if the user is authorized for specific method diff --git a/module/config/gui_default.xml b/module/config/gui_default.xml deleted file mode 100644 index 1faed776f..000000000 --- a/module/config/gui_default.xml +++ /dev/null @@ -1,13 +0,0 @@ -<?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/module/gui/AccountEdit.py b/module/gui/AccountEdit.py deleted file mode 100644 index 83472d4b5..000000000 --- a/module/gui/AccountEdit.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- 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 os.path import join - -class AccountEdit(QWidget): - """ - account editor widget - """ - - def __init__(self): - QMainWindow.__init__(self) - - self.setWindowTitle(_("Edit account")) - self.setWindowIcon(QIcon(join(pypath, "icons", "logo.png"))) - - self.setLayout(QGridLayout()) - l = self.layout() - - typeLabel = QLabel(_("Type")) - loginLabel = QLabel(_("Login")) - passwordLabel = QLabel(_("New password")) - changePw = QCheckBox() - changePw.setChecked(False) - self.changePw = changePw - password = QLineEdit() - password.setEnabled(False) - password.setEchoMode(QLineEdit.Password) - self.password = password - login = QLineEdit() - self.login = login - acctype = QComboBox() - self.acctype = acctype - - save = QPushButton(_("Save")) - - self.connect(changePw, SIGNAL("toggled(bool)"), password, SLOT("setEnabled(bool)")) - - l.addWidget(save, 3, 0, 1, 3) - l.addWidget(acctype, 0, 1, 1, 2) - l.addWidget(login, 1, 1, 1, 2) - l.addWidget(password, 2, 2) - l.addWidget(changePw, 2, 1) - l.addWidget(passwordLabel, 2, 0) - l.addWidget(loginLabel, 1, 0) - l.addWidget(typeLabel, 0, 0) - - self.connect(save, SIGNAL("clicked()"), self.slotSave) - - def slotSave(self): - """ - save entered data - """ - data = {"login": str(self.login.text()), "acctype": str(self.acctype.currentText()), "password": False} - if self.changePw.isChecked(): - data["password"] = str(self.password.text()) - self.emit(SIGNAL("done"), data) - - @staticmethod - def newAccount(types): - """ - create empty editor instance - """ - w = AccountEdit() - w.setWindowTitle(_("Create account")) - - w.changePw.setChecked(True) - w.password.setEnabled(True) - - w.acctype.addItems(types) - - return w - - @staticmethod - def editAccount(types, base): - """ - create editor instance with given data - """ - w = AccountEdit() - - w.acctype.addItems(types) - w.acctype.setCurrentIndex(types.index(base["type"])) - - w.login.setText(base["login"]) - - return w diff --git a/module/gui/Accounts.py b/module/gui/Accounts.py deleted file mode 100644 index 4abd8752c..000000000 --- a/module/gui/Accounts.py +++ /dev/null @@ -1,212 +0,0 @@ -# -*- 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): - """ - model for account view - """ - - 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, force=False): - """ - reload account list - """ - accounts = self.connector.proxy.getAccounts(False) - - if self._data == accounts: - return - - if len(self._data) > 0: - self.beginRemoveRows(QModelIndex(), 0, len(self._data)-1) - self._data = [] - self.endRemoveRows() - - if len(accounts) > 0: - self.beginInsertRows(QModelIndex(), 0, len(accounts)-1) - self._data = accounts - self.endInsertRows() - - def toData(self, index): - """ - return index pointer - """ - return index.internalPointer() - - def data(self, index, role=Qt.DisplayRole): - """ - return cell data - """ - 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).valid: - return QVariant(_("not valid")) - 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 role == Qt.EditRole: - # if index.column() == 0: - # return QVariant(index.internalPointer().data["name"]) - return QVariant() - - def index(self, row, column, parent=QModelIndex()): - """ - create index with data pointer - """ - 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): - """ - no parents, everything on top level - """ - return QModelIndex() - - def rowCount(self, parent=QModelIndex()): - """ - account count - """ - if parent == QModelIndex(): - return len(self._data) - return 0 - - def columnCount(self, parent=QModelIndex()): - return self.cols - - def hasChildren(self, parent=QModelIndex()): - """ - everything on top level - """ - if parent == QModelIndex(): - return True - else: - return False - - def canFetchMore(self, parent): - return False - - def headerData(self, section, orientation, role=Qt.DisplayRole): - """ - returns column heading - """ - 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): - """ - cell flags - """ - return Qt.ItemIsSelectable | Qt.ItemIsEnabled - -class AccountView(QTreeView): - """ - view component for accounts - """ - - 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): - """ - used to display a progressbar for the traffic in the traffic cell - """ - - def __init__(self, parent, model): - QItemDelegate.__init__(self, parent) - self.model = model - - def paint(self, painter, option, index): - """ - paint the progressbar - """ - 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 or data.trafficleft is None: - 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")) - elif data.trafficleft is None: - opts.text = QString(_("n/a")) - 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/module/gui/CNLServer.py b/module/gui/CNLServer.py deleted file mode 100644 index 295cfa045..000000000 --- a/module/gui/CNLServer.py +++ /dev/null @@ -1,226 +0,0 @@ -# -*- 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: RaNaN -""" -import re -from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler -from threading import Thread -from cgi import FieldStorage -from os.path import abspath, dirname, join -from urllib import unquote -from base64 import standard_b64decode -from binascii import unhexlify - -try: - from Crypto.Cipher import AES -except: - pass - -try: - from module.common import JsEngine -except ImportError: - import sys - sys.path.append(join(abspath(dirname(__file__)), "..", "..")) - from module.common import JsEngine - -js = JsEngine.JsEngine() -core = None - -class CNLServer(Thread): - def __init__(self): - Thread.__init__(self) - self.setDaemon(True) - - self.stop = False - self.stopped = False - - def run(self): - server_address = ('127.0.0.1', 9666) - try: - httpd = HTTPServer(server_address, CNLHandler) - except: - self.stopped = True - return - - self.stopped = False - while self.keep_running(): - httpd.handle_request() - self.stopped = True - - def keep_running(self): - return not self.stop - - -class CNLHandler(BaseHTTPRequestHandler): - - #def log_message(self, *args): - # pass - - def add_package(self, name, urls, queue=0): - print "name", name - print "urls", urls - print "queue", queue - - def get_post(self, name, default=""): - if name in self.post: - return self.post[name] - else: - return default - - def start_response(self, string): - - self.send_response(200) - - self.send_header("Content-Length", len(string)) - self.send_header("Content-Language", "de") - self.send_header("Vary", "Accept-Language, Cookie") - self.send_header("Cache-Control", "no-cache, must-revalidate") - self.send_header("Content-type", "text/html") - self.end_headers() - - def do_GET(self): - path = self.path.strip("/").lower() - #self.wfile.write(path+"\n") - - self.map = [ (r"add$", self.add), - (r"addcrypted$", self.addcrypted), - (r"addcrypted2$", self.addcrypted2), - (r"flashgot", self.flashgot), - (r"crossdomain\.xml", self.crossdomain), - (r"checkSupportForUrl", self.checksupport), - (r"jdcheck.js", self.jdcheck), - (r"", self.flash) ] - - func = None - for r, f in self.map: - if re.match(r"(flash(got)?/?)?"+r, path): - func = f - break - - if func: - try: - resp = func() - if not resp: resp = "success" - resp += "\r\n" - self.start_response(resp) - self.wfile.write(resp) - except Exception, e: - self.send_error(500, str(e)) - else: - self.send_error(404, "Not Found") - - def do_POST(self): - form = FieldStorage( - fp=self.rfile, - headers=self.headers, - environ={'REQUEST_METHOD':'POST', - 'CONTENT_TYPE':self.headers['Content-Type'], - }) - - self.post = {} - for name in form.keys(): - self.post[name] = form[name].value - - return self.do_GET() - - def flash(self): - return "JDownloader" - - def add(self): - package = self.get_post('referer', 'ClickAndLoad Package') - urls = filter(lambda x: x != "", self.get_post('urls').split("\n")) - - self.add_package(package, urls, 0) - - def addcrypted(self): - package = self.get_post('referer', 'ClickAndLoad Package') - dlc = self.get_post('crypted').replace(" ", "+") - - core.upload_container(package, dlc) - - def addcrypted2(self): - package = self.get_post("source", "ClickAndLoad Package") - crypted = self.get_post("crypted") - jk = self.get_post("jk") - - crypted = standard_b64decode(unquote(crypted.replace(" ", "+"))) - jk = "%s f()" % jk - jk = js.eval(jk) - Key = unhexlify(jk) - IV = Key - - obj = AES.new(Key, AES.MODE_CBC, IV) - result = obj.decrypt(crypted).replace("\x00", "").replace("\r", "").split("\n") - - result = filter(lambda x: x != "", result) - - self.add_package(package, result, 0) - - - def flashgot(self): - autostart = int(self.get_post('autostart', 0)) - package = self.get_post('package', "FlashGot") - urls = filter(lambda x: x != "", self.get_post('urls').split("\n")) - - self.add_package(package, urls, autostart) - - def crossdomain(self): - rep = "<?xml version=\"1.0\"?>\n" - rep += "<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n" - rep += "<cross-domain-policy>\n" - rep += "<allow-access-from domain=\"*\" />\n" - rep += "</cross-domain-policy>" - return rep - - def checksupport(self): - pass - - def jdcheck(self): - rep = "jdownloader=true;\n" - rep += "var version='10629';\n" - return rep - - -if __name__ == "__main__": - import xmlrpclib - from module import InitHomeDir - from module.ConfigParser import ConfigParser - - config = ConfigParser() - - ssl = "" - if config.get("ssl", "activated"): - ssl = "s" - - server_url = "http%s://%s:%s@%s:%s/" % ( - ssl, - config.username, - config.password, - config.get("remote", "listenaddr"), - config.get("remote", "port") - ) - - core = xmlrpclib.ServerProxy(server_url, allow_none=True) - - s = CNLServer() - s.start() - while not s.stopped: - try: - s.join(1) - except KeyboardInterrupt: - s.stop = True - s.stopped = True - print "quiting.." diff --git a/module/gui/CaptchaDock.py b/module/gui/CaptchaDock.py deleted file mode 100644 index 8d924537f..000000000 --- a/module/gui/CaptchaDock.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- 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): - """ - dock widget for captcha input - """ - - 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): - """ - widget for the input widgets - """ - - 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) - self.input.setFocus(Qt.OtherFocusReason) - - 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/module/gui/Collector.py b/module/gui/Collector.py deleted file mode 100644 index 47da2bada..000000000 --- a/module/gui/Collector.py +++ /dev/null @@ -1,406 +0,0 @@ -# -*- 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.PyFile import statusMap -from module.utils import formatSize - -from module.remote.thriftbackend.ThriftClient import Destination, FileDoesNotExists, ElementType - -statusMapReverse = dict((v, k) for k, v in statusMap.iteritems()) - -translatedStatusMap = {} # -> CollectorModel.__init__ - -class CollectorModel(QAbstractItemModel): - """ - model for the collector view - """ - - def __init__(self, view, connector): - QAbstractItemModel.__init__(self) - self.connector = connector - self.view = view - self._data = [] - self.cols = 4 - self.interval = 1 - self.mutex = QMutex() - - global translatedStatusMap # workaround because i18n is not running at import time - translatedStatusMap = { - "finished": _("finished"), - "offline": _("offline"), - "online": _("online"), - "queued": _("queued"), - "skipped": _("skipped"), - "waiting": _("waiting"), - "temp. offline": _("temp. offline"), - "starting": _("starting"), - "failed": _("failed"), - "aborted": _("aborted"), - "decrypting": _("decrypting"), - "custom": _("custom"), - "downloading": _("downloading"), - "processing": _("processing") - } - - def translateStatus(self, string): - """ - used to convert to locale specific status - """ - return translatedStatusMap[string] - - def addEvent(self, event): - """ - called from main loop, pass events to the correct methods - """ - QMutexLocker(self.mutex) - if event.eventname == "reload": - self.fullReload() - elif event.eventname == "remove": - self.removeEvent(event) - elif event.eventname == "insert": - self.insertEvent(event) - elif event.eventname == "update": - self.updateEvent(event) - - def fullReload(self): - """ - reload whole model, used at startup to load initial data - """ - self._data = [] - order = self.connector.getPackageOrder(Destination.Collector) - self.beginInsertRows(QModelIndex(), 0, len(order.values())) - for position, pid in order.iteritems(): - pack = self.connector.getPackageData(pid) - package = Package(pack) - self._data.append(package) - self._data = sorted(self._data, key=lambda p: p.data["order"]) - self.endInsertRows() - - def removeEvent(self, event): - """ - remove an element from model - """ - if event.type == ElementType.File: - for p, package in enumerate(self._data): - for k, child in enumerate(package.children): - if child.id == event.id: - 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 == event.id: - self.beginRemoveRows(QModelIndex(), k, k) - del self._data[k] - self.endRemoveRows() - break - - def insertEvent(self, event): - """ - inserts a new element in the model - """ - if event.type == ElementType.File: - try: - info = self.connector.getFileData(event.id) - except FileDoesNotExists: - return - - for k, package in enumerate(self._data): - if package.id == info.package: - if package.getChild(info.fid): - self.updateEvent(event) - break - self.beginInsertRows(self.index(k, 0), info.order, info.order) - package.addChild(info) - self.endInsertRows() - break - else: - data = self.connector.getPackageData(event.id) - package = Package(data) - self.beginInsertRows(QModelIndex(), data.order, data.order) - self._data.insert(data.order, package) - self.endInsertRows() - - def updateEvent(self, event): - """ - update an element in the model - """ - if event.type == ElementType.File: - try: - info = self.connector.proxy.getFileData(event.id) - except FileDoesNotExists: - return - for p, package in enumerate(self._data): - if package.id == info.packageID: - for k, child in enumerate(package.children): - if child.id == event.id: - child.update(info) - if not info.status == 12: - 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.getPackageData(event.id) - if not data: - return - for p, package in enumerate(self._data): - if package.id == event.id: - package.update(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): - """ - return cell data - """ - 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 - 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(self.translateStatus(statusMapReverse[status])) - elif index.column() == 3: - item = index.internalPointer() - if isinstance(item, Link): - return QVariant(formatSize(item.data["size"])) - else: - ms = 0 - for c in item.children: - ms += c.data["size"] - return QVariant(formatSize(ms)) - elif role == Qt.EditRole: - if index.column() == 0: - return QVariant(index.internalPointer().data["name"]) - return QVariant() - - def index(self, row, column, parent=QModelIndex()): - """ - creates a cell index with pointer to the data - """ - if parent == QModelIndex() and len(self._data) > row: - pointer = self._data[row] - index = self.createIndex(row, column, pointer) - elif parent.isValid(): - try: - pointer = parent.internalPointer().children[row] - except: - return QModelIndex() - index = self.createIndex(row, column, pointer) - else: - index = QModelIndex() - return index - - def parent(self, index): - """ - return index of parent element - only valid for links - """ - 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()): - """ - returns row count for the element - """ - 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): - """ - returns column heading - """ - if orientation == Qt.Horizontal and role == Qt.DisplayRole: - if section == 0: - return QVariant(_("Name")) - elif section == 1: - return QVariant(_("Plugin")) - elif section == 2: - return QVariant(_("Status")) - elif section == 3: - return QVariant(_("Size")) - return QVariant() - - def flags(self, index): - """ - cell flags - """ - 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): - """ - called if package name editing is finished, sets new name - """ - 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): - """ - package object in the model - """ - - def __init__(self, pack): - self.id = pack.pid - self.children = [] - for f in pack.links: - self.addChild(f) - self.data = {} - self.update(pack) - - def update(self, pack): - """ - update data dict from thift object - """ - data = { - "name": pack.name, - "folder": pack.folder, - "site": pack.site, - "password": pack.password, - "order": pack.order, - } - self.data.update(data) - - def addChild(self, f): - """ - add child (Link) to package - """ - self.children.insert(f.order, Link(f, self)) - self.children = sorted(self.children, key=lambda l: l.data["order"]) - - def getChild(self, fid): - """ - get child from package - """ - for child in self.children: - if child.id == int(fid): - return child - return None - - def getChildKey(self, fid): - """ - get child index - """ - for k, child in enumerate(self.children): - if child.id == int(fid): - return k - return None - - def removeChild(self, fid): - """ - remove child - """ - for k, child in enumerate(self.children): - if child.id == int(fid): - del self.children[k] - -class Link(object): - def __init__(self, f, pack): - self.data = {"downloading": None} - self.update(f) - self.id = f.fid - self.package = pack - - def update(self, f): - """ - update data dict from thift object - """ - data = { - "url": f.url, - "name": f.name, - "plugin": f.plugin, - "size": f.size, - "format_size": f.format_size, - "status": f.status, - "statusmsg": f.statusmsg, - "package": f.packageID, - "error": f.error, - "order": f.order, - } - self.data.update(data) - -class CollectorView(QTreeView): - """ - view component for collector - """ - - 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.setColumnWidth(3, 100) - - self.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed) diff --git a/module/gui/ConnectionManager.py b/module/gui/ConnectionManager.py deleted file mode 100644 index eb6e68f02..000000000 --- a/module/gui/ConnectionManager.py +++ /dev/null @@ -1,301 +0,0 @@ -# -*- 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 os.path import join - -from uuid import uuid4 as uuid - -class ConnectionManager(QWidget): - - - warningShown = False - - def __init__(self): - QWidget.__init__(self) - - if not self.warningShown: - QMessageBox.warning(self, 'Warning', - "We are sorry but the GUI is not stable yet. Please use the webinterface for much better experience. \n", QMessageBox.Ok) - ConnectionManager.warningShown = True - - mainLayout = QHBoxLayout() - buttonLayout = QVBoxLayout() - - self.setWindowTitle(_("pyLoad ConnectionManager")) - self.setWindowIcon(QIcon(join(pypath, "icons", "logo.png"))) - - connList = QListWidget() - - new = QPushButton(_("New")) - edit = QPushButton(_("Edit")) - remove = QPushButton(_("Remove")) - connect = QPushButton(_("Connect")) - - #box = QFrame() - boxLayout = QVBoxLayout() - #box.setLayout(boxLayout) - - boxLayout.addWidget(QLabel(_("Connect:"))) - boxLayout.addWidget(connList) - - line = QFrame() - #line.setFixedWidth(100) - line.setFrameShape(line.HLine) - line.setFrameShadow(line.Sunken) - line.setFixedHeight(10) - - boxLayout.addWidget(line) - - form = QFormLayout() - form.setMargin(5) - form.setSpacing(20) - - form.setAlignment(Qt.AlignRight) - checkbox = QCheckBox() - form.addRow(_("Use internal Core:"), checkbox) - - boxLayout.addLayout(form) - - mainLayout.addLayout(boxLayout) - mainLayout.addLayout(buttonLayout) - - buttonLayout.addWidget(new) - buttonLayout.addWidget(edit) - buttonLayout.addWidget(remove) - buttonLayout.addStretch() - buttonLayout.addWidget(connect) - - self.setLayout(mainLayout) - - self.internal = checkbox - 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) - self.connect(self.internal, SIGNAL("clicked()"), self.slotInternal) - - 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":"", "port":"7228", "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): - if self.internal.checkState() == 2: - data = {"type": "internal"} - self.emit(SIGNAL("connect"), data) - else: - 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 slotInternal(self): - if self.internal.checkState() == 2: - self.connList.clearSelection() - - 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) - - self.setWindowTitle(_("pyLoad ConnectionManager")) - self.setWindowIcon(QIcon(join(pypath, "icons", "logo.png"))) - - grid = QGridLayout() - - nameLabel = QLabel(_("Name:")) - hostLabel = QLabel(_("Host:")) - localLabel = QLabel(_("Local:")) - userLabel = QLabel(_("User:")) - pwLabel = QLabel(_("Password:")) - portLabel = QLabel(_("Port:")) - - name = QLineEdit() - host = QLineEdit() - 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(userLabel, 4, 0) - grid.addWidget(user, 4, 1) - grid.addWidget(pwLabel, 5, 0) - grid.addWidget(password, 5, 1) - grid.addWidget(cancel, 6, 0) - grid.addWidget(save, 6, 1) - - self.setLayout(grid) - self.controls = {"name": name, - "host": host, - "local": local, - "user": user, - "password": password, - "port": port, - "save": save, - "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): - if not data: return - - 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["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["user"].setDisabled(False) - self.controls["password"].setDisabled(False) - self.controls["port"].setDisabled(False) - self.controls["host"].setDisabled(False) - else: - self.controls["user"].setText("") - self.controls["port"].setValue(1) - self.controls["host"].setText("") - 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["user"].setDisabled(True) - self.controls["password"].setDisabled(True) - self.controls["port"].setDisabled(True) - self.controls["host"].setDisabled(True) - elif val == 0: - 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["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/module/gui/CoreConfigParser.py b/module/gui/CoreConfigParser.py deleted file mode 100644 index cf0c24868..000000000 --- a/module/gui/CoreConfigParser.py +++ /dev/null @@ -1,162 +0,0 @@ -# -*- 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/module/gui/LinkDock.py b/module/gui/LinkDock.py deleted file mode 100644 index 66822218d..000000000 --- a/module/gui/LinkDock.py +++ /dev/null @@ -1,56 +0,0 @@ -# -*- 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() - - explanationLabel = QLabel("Select a package and then click Add button.") - boxLabel = QLabel("Paste URLs here:") - self.box = QTextEdit() - - save = QPushButton("Add") - - layout.addWidget(explanationLabel) - layout.addWidget(boxLabel) - layout.addWidget(self.box) - layout.addWidget(save) - - self.connect(save, SIGNAL("clicked()"), self.dock.slotDone) diff --git a/module/gui/MainWindow.py b/module/gui/MainWindow.py deleted file mode 100644 index 85a3bb59c..000000000 --- a/module/gui/MainWindow.py +++ /dev/null @@ -1,697 +0,0 @@ -# -*- 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 os.path import join - -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.Overview import OverviewView -from module.gui.Accounts import AccountView -from module.gui.AccountEdit import AccountEdit - -from module.remote.thriftbackend.ThriftClient import AccountInfo - -class MainWindow(QMainWindow): - def __init__(self, connector): - """ - set up main window - """ - QMainWindow.__init__(self) - #window stuff - self.setWindowTitle(_("pyLoad Client")) - self.setWindowIcon(QIcon(join(pypath, "icons", "logo.png"))) - self.resize(1000, 600) - - #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) - self.newLinkDock = NewLinkDock() - self.addDockWidget(Qt.RightDockWidgetArea, self.newLinkDock) - self.connect(self.newLinkDock, SIGNAL("done"), self.slotAddLinksToPackage) - - #central widget, layout - self.masterlayout = QVBoxLayout() - lw = QWidget() - lw.setLayout(self.masterlayout) - self.setCentralWidget(lw) - - #status - self.statusw = QFrame() - self.statusw.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) - self.statusw.setLineWidth(2) - self.statusw.setLayout(QGridLayout()) - #palette = self.statusw.palette() - #palette.setColor(QPalette.Window, QColor(255, 255, 255)) - #self.statusw.setPalette(palette) - #self.statusw.setAutoFillBackground(True) - l = self.statusw.layout() - - class BoldLabel(QLabel): - def __init__(self, text): - QLabel.__init__(self, text) - f = self.font() - f.setBold(True) - self.setFont(f) - self.setAlignment(Qt.AlignRight) - - class Seperator(QFrame): - def __init__(self): - QFrame.__init__(self) - self.setFrameShape(QFrame.VLine) - self.setFrameShadow(QFrame.Sunken) - - l.addWidget(BoldLabel(_("Packages:")), 0, 0) - self.packageCount = QLabel("0") - l.addWidget(self.packageCount, 0, 1) - - l.addWidget(BoldLabel(_("Files:")), 0, 2) - self.fileCount = QLabel("0") - l.addWidget(self.fileCount, 0, 3) - - l.addWidget(BoldLabel(_("Status:")), 0, 4) - self.status = QLabel("running") - l.addWidget(self.status, 0, 5) - - l.addWidget(BoldLabel(_("Space:")), 0, 6) - self.space = QLabel("") - l.addWidget(self.space, 0, 7) - - l.addWidget(BoldLabel(_("Speed:")), 0, 8) - self.speed = QLabel("") - l.addWidget(self.speed, 0, 9) - - #l.addWidget(BoldLabel(_("Max. downloads:")), 0, 9) - #l.addWidget(BoldLabel(_("Max. chunks:")), 1, 9) - #self.maxDownloads = QSpinBox() - #self.maxDownloads.setEnabled(False) - #self.maxChunks = QSpinBox() - #self.maxChunks.setEnabled(False) - #l.addWidget(self.maxDownloads, 0, 10) - #l.addWidget(self.maxChunks, 1, 10) - - #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 = {"file": self.menubar.addMenu(_("File")), - "connections": self.menubar.addMenu(_("Connections"))} - - #menu actions - self.mactions = {"exit": QAction(_("Exit"), self.menus["file"]), - "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 = {"overview": {"w": QWidget()}, - "queue": {"w": QWidget()}, - "collector": {"w": QWidget()}, - "accounts": {"w": QWidget()}, - "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["overview"]["w"], _("Overview")) - 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"]["w"], _("Settings")) - self.tabw.addTab(self.tabs["log"]["w"], _("Log")) - - #init tabs - self.init_tabs(connector) - - #context menus - self.init_context() - - #layout - self.masterlayout.addWidget(self.tabw) - self.masterlayout.addWidget(self.statusw) - - #signals.. - self.connect(self.mactions["manager"], SIGNAL("triggered()"), self.slotShowConnector) - - 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.tabs["accounts"]["view"], SIGNAL('customContextMenuRequested(const QPoint &)'), self.slotAccountContextMenu) - - self.connect(self.tabw, SIGNAL("currentChanged(int)"), self.slotTabChanged) - - self.lastAddedID = None - - self.connector = connector - - def init_toolbar(self): - """ - create toolbar - """ - self.toolbar = self.addToolBar(_("Hide Toolbar")) - self.toolbar.setObjectName("Main Toolbar") - self.toolbar.setIconSize(QSize(30, 30)) - self.toolbar.setMovable(False) - self.actions["toggle_status"] = self.toolbar.addAction(_("Toggle Pause/Resume")) - pricon = QIcon() - pricon.addFile(join(pypath, "icons", "toolbar_start.png"), QSize(), QIcon.Normal, QIcon.Off) - pricon.addFile(join(pypath, "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(join(pypath, "icons", "toolbar_stop.png")), _("Stop")) - self.toolbar.addSeparator() - self.actions["add"] = self.toolbar.addAction(QIcon(join(pypath, "icons", "toolbar_add.png")), _("Add")) - self.toolbar.addSeparator() - self.actions["clipboard"] = self.toolbar.addAction(QIcon(join(pypath, "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")) - accountAction = self.addMenu.addAction(_("Account")) - linksAction = self.addMenu.addAction(_("Links")) - self.connect(self.actions["add"], SIGNAL("triggered()"), self.slotAdd) - self.connect(packageAction, SIGNAL("triggered()"), self.slotShowAddPackage) - self.connect(containerAction, SIGNAL("triggered()"), self.slotShowAddContainer) - self.connect(accountAction, SIGNAL("triggered()"), self.slotNewAccount) - self.connect(linksAction, SIGNAL("triggered()"), self.slotShowAddLinks) - - def init_tabs(self, connector): - """ - create tabs - """ - #overview - self.tabs["overview"]["l"] = QGridLayout() - self.tabs["overview"]["w"].setLayout(self.tabs["overview"]["l"]) - self.tabs["overview"]["view"] = OverviewView(connector) - self.tabs["overview"]["l"].addWidget(self.tabs["overview"]["view"]) - - #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(QVBoxLayout()) - self.tabs["accounts"]["w"].layout().addWidget(self.tabs["accounts"]["view"]) - newbutton = QPushButton(_("New Account")) - self.tabs["accounts"]["w"].layout().addWidget(newbutton) - self.connect(newbutton, SIGNAL("clicked()"), self.slotNewAccount) - self.tabs["accounts"]["view"].setContextMenuPolicy(Qt.CustomContextMenu) - - 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(join(pypath, "icons", "remove_small.png")), _("Remove"), self.queueContext) - self.queueContext.buttons["restart"] = QAction(QIcon(join(pypath, "icons", "refresh_small.png")), _("Restart"), self.queueContext) - self.queueContext.buttons["pull"] = QAction(QIcon(join(pypath, "icons", "pull_small.png")), _("Pull out"), self.queueContext) - self.queueContext.buttons["abort"] = QAction(QIcon(join(pypath, "icons", "abort.png")), _("Abort"), self.queueContext) - self.queueContext.buttons["edit"] = QAction(QIcon(join(pypath, "icons", "edit_small.png")), _("Edit Name"), self.queueContext) - 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.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) - - #collector - self.collectorContext = QMenu() - self.collectorContext.buttons = {} - self.collectorContext.item = (None, None) - self.collectorContext.buttons["remove"] = QAction(QIcon(join(pypath, "icons", "remove_small.png")), _("Remove"), self.collectorContext) - self.collectorContext.buttons["push"] = QAction(QIcon(join(pypath, "icons", "push_small.png")), _("Push to queue"), self.collectorContext) - self.collectorContext.buttons["edit"] = QAction(QIcon(join(pypath, "icons", "edit_small.png")), _("Edit Name"), self.collectorContext) - self.collectorContext.buttons["restart"] = QAction(QIcon(join(pypath, "icons", "refresh_small.png")), _("Restart"), self.collectorContext) - self.collectorContext.buttons["refresh"] = QAction(QIcon(join(pypath, "icons", "refresh1_small.png")), _("Refresh Status"), self.collectorContext) - self.collectorContext.addAction(self.collectorContext.buttons["push"]) - self.collectorContext.addSeparator() - self.collectorContext.buttons["add"] = self.collectorContext.addMenu(QIcon(join(pypath, "icons", "add_small.png")), _("Add")) - self.collectorContext.addAction(self.collectorContext.buttons["edit"]) - self.collectorContext.addAction(self.collectorContext.buttons["remove"]) - self.collectorContext.addAction(self.collectorContext.buttons["restart"]) - self.collectorContext.addSeparator() - self.collectorContext.addAction(self.collectorContext.buttons["refresh"]) - packageAction = self.collectorContext.buttons["add"].addAction(_("Package")) - containerAction = self.collectorContext.buttons["add"].addAction(_("Container")) - linkAction = self.collectorContext.buttons["add"].addAction(_("Links")) - 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) - self.connect(self.collectorContext.buttons["restart"], SIGNAL("triggered()"), self.slotRestartDownload) - self.connect(self.collectorContext.buttons["refresh"], SIGNAL("triggered()"), self.slotRefreshPackage) - self.connect(packageAction, SIGNAL("triggered()"), self.slotShowAddPackage) - self.connect(containerAction, SIGNAL("triggered()"), self.slotShowAddContainer) - self.connect(linkAction, SIGNAL("triggered()"), self.slotShowAddLinks) - - self.accountContext = QMenu() - self.accountContext.buttons = {} - self.accountContext.buttons["add"] = QAction(QIcon(join(pypath, "icons", "add_small.png")), _("Add"), self.accountContext) - self.accountContext.buttons["remove"] = QAction(QIcon(join(pypath, "icons", "remove_small.png")), _("Remove"), self.accountContext) - self.accountContext.buttons["edit"] = QAction(QIcon(join(pypath, "icons", "edit_small.png")), _("Edit"), self.accountContext) - self.accountContext.addAction(self.accountContext.buttons["add"]) - self.accountContext.addAction(self.accountContext.buttons["edit"]) - self.accountContext.addAction(self.accountContext.buttons["remove"]) - self.connect(self.accountContext.buttons["add"], SIGNAL("triggered()"), self.slotNewAccount) - self.connect(self.accountContext.buttons["edit"], SIGNAL("triggered()"), self.slotEditAccount) - self.connect(self.accountContext.buttons["remove"], SIGNAL("triggered()"), self.slotRemoveAccount) - - 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, password=None): - """ - new package - let main to the stuff - """ - self.emit(SIGNAL("addPackage"), name, links, password) - - def slotAddLinksToPackage(self, links): - """ - adds links to currently selected package - only in collector - """ - if self.tabw.currentIndex() != 1: - return - - smodel = self.tabs["collector"]["package_view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - if isinstance(item, Package): - self.connector.proxy.addFiles(item.id, links) - break - - 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.ignore() - self.hide() - self.emit(SIGNAL("hidden")) - - # quit when no tray is available - if not QSystemTrayIcon.isSystemTrayAvailable(): - 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 - break - if showAbort: - self.queueContext.buttons["abort"].setEnabled(True) - else: - self.queueContext.buttons["abort"].setEnabled(False) - if isinstance(item, Package): - self.queueContext.index = i - #self.queueContext.buttons["remove"].setEnabled(True) - #self.queueContext.buttons["restart"].setEnabled(True) - self.queueContext.buttons["pull"].setEnabled(True) - self.queueContext.buttons["edit"].setEnabled(True) - elif isinstance(item, Link): - self.collectorContext.index = i - self.collectorContext.buttons["edit"].setEnabled(False) - self.collectorContext.buttons["remove"].setEnabled(True) - self.collectorContext.buttons["push"].setEnabled(False) - self.collectorContext.buttons["restart"].setEnabled(True) - else: - self.queueContext.index = None - #self.queueContext.buttons["remove"].setEnabled(False) - #self.queueContext.buttons["restart"].setEnabled(False) - self.queueContext.buttons["pull"].setEnabled(False) - self.queueContext.buttons["edit"].setEnabled(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"].setEnabled(True) - self.collectorContext.buttons["remove"].setEnabled(True) - self.collectorContext.buttons["push"].setEnabled(True) - self.collectorContext.buttons["restart"].setEnabled(True) - elif isinstance(item, Link): - self.collectorContext.index = i - self.collectorContext.buttons["edit"].setEnabled(False) - self.collectorContext.buttons["remove"].setEnabled(True) - self.collectorContext.buttons["push"].setEnabled(False) - self.collectorContext.buttons["restart"].setEnabled(True) - else: - self.collectorContext.index = None - self.collectorContext.buttons["edit"].setEnabled(False) - self.collectorContext.buttons["remove"].setEnabled(False) - self.collectorContext.buttons["push"].setEnabled(False) - self.collectorContext.buttons["restart"].setEnabled(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)) - - 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): - # in Queue, only edit name - 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)) - - # TODO disabled because changing desktop on linux, main window disappears - #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() - - def slotRefreshPackage(self): - smodel = self.tabs["collector"]["package_view"].selectionModel() - for index in smodel.selectedRows(0): - item = index.internalPointer() - pid = item.id - if isinstance(item, Link): - pid = item.package.id - self.emit(SIGNAL("refreshStatus"), pid) - - def slotNewAccount(self): - types = self.connector.proxy.getAccountTypes() - self.accountEdit = AccountEdit.newAccount(types) - - #TODO make more easy n1, n2, n3 - def save(data): - if data["password"]: - self.accountEdit.close() - n1 = data["acctype"] - n2 = data["login"] - n3 = data["password"] - self.connector.updateAccount(n1, n2, n3, None) - - self.accountEdit.connect(self.accountEdit, SIGNAL("done"), save) - self.accountEdit.show() - - def slotEditAccount(self): - types = self.connector.getAccountTypes() - - data = self.tabs["accounts"]["view"].selectedIndexes() - if len(data) < 1: - return - - data = data[0].internalPointer() - - self.accountEdit = AccountEdit.editAccount(types, data) - - #TODO make more easy n1, n2, n3 - #TODO reload accounts tab after insert of edit account - #TODO if account does not exist give error - def save(data): - self.accountEdit.close() - n1 = data["acctype"] - n2 = data["login"] - if data["password"]: - n3 = data["password"] - self.connector.updateAccount(n1, n2, n3, None) - - self.accountEdit.connect(self.accountEdit, SIGNAL("done"), save) - self.accountEdit.show() - - def slotRemoveAccount(self): - data = self.tabs["accounts"]["view"].selectedIndexes() - if len(data) < 1: - return - - data = data[0].internalPointer() - - self.connector.removeAccount(data.type, data.login) - - def slotAccountContextMenu(self, pos): - globalPos = self.tabs["accounts"]["view"].mapToGlobal(pos) - i = self.tabs["accounts"]["view"].indexAt(pos) - if not i: - return - - data = i.internalPointer() - - if data is None: - self.accountContext.buttons["edit"].setEnabled(False) - self.accountContext.buttons["remove"].setEnabled(False) - else: - self.accountContext.buttons["edit"].setEnabled(True) - self.accountContext.buttons["remove"].setEnabled(True) - - menuPos = QCursor.pos() - menuPos.setX(menuPos.x()+2) - self.accountContext.exec_(menuPos) diff --git a/module/gui/Overview.py b/module/gui/Overview.py deleted file mode 100644 index 6c9957eba..000000000 --- a/module/gui/Overview.py +++ /dev/null @@ -1,197 +0,0 @@ -# -*- 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.utils import formatSpeed, formatSize - -class OverviewModel(QAbstractListModel): - PackageName = 10 - Progress = 11 - PartsFinished = 12 - Parts = 13 - ETA = 14 - Speed = 15 - CurrentSize = 16 - MaxSize = 17 - Status = 18 - - def __init__(self, view, connector): - QAbstractListModel.__init__(self) - - self.packages = [] - - def queueChanged(self): #dirty.. - self.beginResetModel() - - self.packages = [] - - def partsFinished(p): - f = 0 - for c in p.children: - if c.data["status"] == 0: - f += 1 - return f - - def maxSize(p): - ms = 0 - cs = 0 - for c in p.children: - try: - s = c.data["downloading"]["size"] - except: - s = c.data["size"] - if c.data["downloading"]: - cs += s - c.data["downloading"]["bleft"] - elif self.queue.getProgress(c, False) == 100: - cs += s - ms += s - return ms, cs - - def getProgress(p): - for c in p.children: - if c.data["status"] == 13: - pass # TODO return _("Unpacking"), int(c.data["progress"]) - return _("Downloading"), self.queue.getProgress(p) - - d = self.queue._data - for p in d: - status, progress = getProgress(p) - maxsize, currentsize = maxSize(p) - speed = self.queue.getSpeed(p) - if speed: - eta = (maxsize - (maxsize * (progress/100.0)))/speed - else: - eta = 0 - if not speed and not progress: - status = _("Queued") - info = { - OverviewModel.PackageName: p.data["name"], - OverviewModel.Progress: progress, - OverviewModel.PartsFinished: partsFinished(p), - OverviewModel.Parts: len(p.children), - OverviewModel.ETA: int(eta), - OverviewModel.Speed: speed, - OverviewModel.CurrentSize: currentsize, - OverviewModel.MaxSize: maxsize, - OverviewModel.Status: status, - } - - self.packages.append(info) - - self.endResetModel() - - def headerData(self, section, orientation, role=Qt.DisplayRole): - return QVariant(_("Package")) - - def rowCount(self, parent=QModelIndex()): - return len(self.packages) - - def data(self, index, role=Qt.DisplayRole): - if role in [OverviewModel.PackageName, OverviewModel.Progress, OverviewModel.PartsFinished, OverviewModel.Parts, OverviewModel.ETA, OverviewModel.Speed, OverviewModel.CurrentSize, OverviewModel.MaxSize, OverviewModel.Status]: - return QVariant(self.packages[index.row()][role]) - return QVariant() - -class OverviewView(QListView): - def __init__(self, connector): - QListView.__init__(self) - self.setModel(OverviewModel(self, connector)) - - self.setAlternatingRowColors(True) - self.delegate = OverviewDelegate(self) - self.setItemDelegate(self.delegate) - -class OverviewDelegate(QItemDelegate): - def __init__(self, parent): - QItemDelegate.__init__(self, parent) - self.parent = parent - self.model = parent.model() - - def paint(self, painter, option, index): - option.rect.setHeight(59+16) - option.rect.setWidth(self.parent.width()-20) - - #if option.state & QStyle.State_Selected: - # painter.fillRect(option.rect, option.palette.color(QPalette.Highlight)) - - packagename = index.data(OverviewModel.PackageName).toString() - partsf = index.data(OverviewModel.PartsFinished).toString() - parts = index.data(OverviewModel.Parts).toString() - eta = int(index.data(OverviewModel.ETA).toString()) - speed = index.data(OverviewModel.Speed).toString() or 0 - progress = int(index.data(OverviewModel.Progress).toString()) - currentSize = int(index.data(OverviewModel.CurrentSize).toString()) - maxSize = int(index.data(OverviewModel.MaxSize).toString()) - status = index.data(OverviewModel.Status).toString() - - def formatEta(seconds): #TODO add to utils - if seconds <= 0: return "" - hours, seconds = divmod(seconds, 3600) - minutes, seconds = divmod(seconds, 60) - return _("ETA: ") + "%.2i:%.2i:%.2i" % (hours, minutes, seconds) - - statusline = QString(_("Parts: ") + "%s/%s" % (partsf, parts)) - if partsf == parts: - speedline = _("Finished") - elif not status == _("Downloading"): - speedline = QString(status) - else: - speedline = QString(formatEta(eta) + " " + _("Speed: %s") % formatSpeed(speed)) - - if progress in (0, 100): - sizeline = QString(_("Size:") + "%s" % formatSize(maxSize)) - else: - sizeline = QString(_("Size:") + "%s / %s" % (formatSize(currentSize), formatSize(maxSize))) - - f = painter.font() - f.setPointSize(12) - f.setBold(True) - painter.setFont(f) - - r = option.rect.adjusted(4, 4, -4, -4) - painter.drawText(r.left(), r.top(), r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, packagename) - newr = painter.boundingRect(r.left(), r.top(), r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, packagename) - - f.setPointSize(10) - f.setBold(False) - painter.setFont(f) - - painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, statusline) - painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignHCenter, sizeline) - painter.drawText(r.left(), newr.bottom()+5, r.width(), r.height(), Qt.AlignTop | Qt.AlignRight, speedline) - newr = painter.boundingRect(r.left(), newr.bottom()+2, r.width(), r.height(), Qt.AlignTop | Qt.AlignLeft, statusline) - newr.setTop(newr.bottom()+8) - newr.setBottom(newr.top()+20) - newr.setRight(self.parent.width()-25) - - f.setPointSize(10) - painter.setFont(f) - - opts = QStyleOptionProgressBarV2() - opts.maximum = 100 - opts.minimum = 0 - opts.progress = progress - opts.rect = newr - opts.textVisible = True - opts.textAlignment = Qt.AlignCenter - opts.text = QString.number(opts.progress) + "%" - QApplication.style().drawControl(QStyle.CE_ProgressBar, opts, painter) - - def sizeHint(self, option, index): - return QSize(self.parent.width()-22, 59+16) diff --git a/module/gui/PackageDock.py b/module/gui/PackageDock.py deleted file mode 100644 index a4bc02f93..000000000 --- a/module/gui/PackageDock.py +++ /dev/null @@ -1,90 +0,0 @@ -# -*- 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 -""" -import re - -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()) - pw = str(self.widget.passwordInput.text()) - if not pw: - pw = None - 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, pw) - self.widget.nameInput.setText("") - self.widget.passwordInput.setText("") - self.widget.box.clear() - self.hide() - - def parseUri(self): - - text=str(self.widget.box.toPlainText()) - self.widget.box.setText("") - result = re.findall(r"(?:ht|f)tps?:\/\/[a-zA-Z0-9\-\.\/\?=_&%#]+[<| |\"|\'|\r|\n|\t]{1}", text) - for url in result: - if "\n" or "\t" or "\r" or "\"" or "<" or "'" in url: - url = url[:-1] - self.widget.box.append("%s " % url) - -class NewPackageWindow(QWidget): - def __init__(self, dock): - QWidget.__init__(self) - self.dock = dock - self.setLayout(QGridLayout()) - layout = self.layout() - - nameLabel = QLabel(_("Name")) - nameInput = QLineEdit() - passwordLabel = QLabel(_("Password")) - passwordInput = QLineEdit() - - linksLabel = QLabel(_("Links in this Package")) - - self.box = QTextEdit() - self.nameInput = nameInput - self.passwordInput = passwordInput - - save = QPushButton(_("Create")) - parseUri = QPushButton(_("Filter URLs")) - - layout.addWidget(nameLabel, 0, 0) - layout.addWidget(nameInput, 0, 1) - layout.addWidget(passwordLabel, 1, 0) - layout.addWidget(passwordInput, 1, 1) - layout.addWidget(linksLabel, 2, 0, 1, 2) - layout.addWidget(self.box, 3, 0, 1, 2) - layout.addWidget(parseUri, 4, 0, 1, 2) - layout.addWidget(save, 5, 0, 1, 2) - - self.connect(save, SIGNAL("clicked()"), self.dock.slotDone) - self.connect(parseUri, SIGNAL("clicked()"), self.dock.parseUri) diff --git a/module/gui/Queue.py b/module/gui/Queue.py deleted file mode 100644 index afbcc00f8..000000000 --- a/module/gui/Queue.py +++ /dev/null @@ -1,389 +0,0 @@ -# -*- 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 time - -from module.remote.thriftbackend.ThriftClient import Destination -from module.gui.Collector import CollectorModel, Package, Link, CollectorView, statusMapReverse -from module.utils import formatSize, formatSpeed - -class QueueModel(CollectorModel): - """ - model for the queue view, inherits from CollectorModel - """ - - def __init__(self, view, connector): - CollectorModel.__init__(self, view, connector) - self.cols = 6 - self.wait_dict = {} - - self.updater = self.QueueUpdater(self.interval) - self.connect(self.updater, SIGNAL("update()"), self.update) - - class QueueUpdater(QObject): - """ - timer which emits signal for a download status reload - @TODO: make intervall configurable - """ - - 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): - """ - reimplements CollectorModel.fullReload, because we want the Queue data - """ - self._data = [] - order = self.connector.getPackageOrder(Destination.Queue) - self.beginInsertRows(QModelIndex(), 0, len(order.values())) - for position, pid in order.iteritems(): - pack = self.connector.getPackageData(pid) - package = Package(pack) - self._data.append(package) - self._data = sorted(self._data, key=lambda p: p.data["order"]) - self.endInsertRows() - self.updateCount() - - def insertEvent(self, event): - """ - wrap CollectorModel.insertEvent to update the element count - """ - CollectorModel.insertEvent(self, event) - self.updateCount() - - def removeEvent(self, event): - """ - wrap CollectorModel.removeEvent to update the element count - """ - CollectorModel.removeEvent(self, event) - self.updateCount() - - def updateEvent(self, event): - """ - wrap CollectorModel.updateEvent to update the element count - """ - CollectorModel.updateEvent(self, event) - self.updateCount() - - def updateCount(self): - """ - calculate package- and filecount for statusbar, - ugly?: Overview connects to this signal for updating - """ - packageCount = len(self._data) - fileCount = 0 - for p in self._data: - fileCount += len(p.children) - self.mutex.unlock() - self.emit(SIGNAL("updateCount"), packageCount, fileCount) - self.mutex.lock() - - def update(self): - """ - update slot for download status updating - """ - locker = QMutexLocker(self.mutex) - downloading = self.connector.statusDownloads() - if not downloading: - return - for p, pack in enumerate(self._data): - for d in downloading: - child = pack.getChild(d.fid) - if child: - dd = { - "name": d.name, - "speed": d.speed, - "eta": d.eta, - "format_eta": d.format_eta, - "bleft": d.bleft, - "size": d.size, - "format_size": d.format_size, - "percent": d.percent, - "status": d.status, - "statusmsg": d.statusmsg, - "format_wait": d.format_wait, - "wait_until": d.wait_until - } - child.data["downloading"] = dd - k = pack.getChildKey(d.fid) - 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))) - self.updateCount() - - def headerData(self, section, orientation, role=Qt.DisplayRole): - """ - returns column heading - """ - 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(_("Size")) - elif section == 4: - return QVariant(_("ETA")) - elif section == 5: - return QVariant(_("Progress")) - return QVariant() - - def getWaitingProgress(self, item): - """ - returns time to wait, caches startingtime to provide progress - """ - 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()) - if rest < 0: - return 0, None - res = 100/max_wait - perc = rest*res - return perc, rest - return None - - def getProgress(self, item, locked=True): - """ - return download progress, locks by default - since it's used in already locked calls, - it provides an option to not lock - """ - if locked: - locker = QMutexLocker(self.mutex) - if isinstance(item, Link): - try: - if item.data["status"] == 0: - return 100 - return int(item.data["downloading"]["percent"]) - except: - return 0 - elif isinstance(item, Package): - count = len(item.children) - perc_sum = 0 - for child in item.children: - try: - if child.data["status"] == 0: #completed - perc_sum += 100 - perc_sum += int(child.data["downloading"]["percent"]) - except: - pass - if count == 0: - return 0 - return perc_sum/count - return 0 - - def getSpeed(self, item): - """ - calculate download speed - """ - 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): - """ - return cell data - """ - 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 is None or status == 7 or status == 10 or status == 5: - return QVariant(self.translateStatus(statusMapReverse[status])) - else: - return QVariant("%s (%s)" % (self.translateStatus(statusMapReverse[status]), formatSpeed(speed))) - elif index.column() == 3: - item = index.internalPointer() - if isinstance(item, Link): - if item.data["status"] == 0: #TODO needs change?? - #self.getProgress(item, False) == 100: - return QVariant(formatSize(item.data["size"])) - elif self.getProgress(item, False) == 0: - try: - return QVariant("%s / %s" % (formatSize(item.data["size"]-item.data["downloading"]["bleft"]), formatSize(item.data["size"]))) - except: - return QVariant("0 B / %s" % formatSize(item.data["size"])) - else: - try: - return QVariant("%s / %s" % (formatSize(item.data["size"]-item.data["downloading"]["bleft"]), formatSize(item.data["size"]))) - except: - return QVariant("? / %s" % formatSize(item.data["size"])) - else: - ms = 0 - cs = 0 - for c in item.children: - try: - s = c.data["downloading"]["size"] - except: - s = c.data["size"] - if c.data["downloading"]: - cs += s - c.data["downloading"]["bleft"] - elif self.getProgress(c, False) == 100: - cs += s - ms += s - if cs == 0 or cs == ms: - return QVariant(formatSize(ms)) - else: - return QVariant("%s / %s" % (formatSize(cs), formatSize(ms))) - elif index.column() == 4: - item = index.internalPointer() - if isinstance(item, Link): - if item.data["downloading"]: - return QVariant(item.data["downloading"]["format_eta"]) - elif role == Qt.EditRole: - if index.column() == 0: - return QVariant(index.internalPointer().data["name"]) - return QVariant() - - def flags(self, index): - """ - cell flags - """ - if index.column() == 0 and self.parent(index) == QModelIndex(): - return Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled - return Qt.ItemIsSelectable | Qt.ItemIsEnabled - -class QueueView(CollectorView): - """ - view component for queue - """ - - def __init__(self, connector): - CollectorView.__init__(self, connector) - self.setModel(QueueModel(self, connector)) - - self.setColumnWidth(0, 300) - self.setColumnWidth(1, 100) - self.setColumnWidth(2, 140) - self.setColumnWidth(3, 180) - self.setColumnWidth(4, 70) - - self.setEditTriggers(QAbstractItemView.NoEditTriggers) - - self.delegate = QueueProgressBarDelegate(self, self.model()) - self.setItemDelegateForColumn(5, self.delegate) - -class QueueProgressBarDelegate(QItemDelegate): - """ - used to display a progressbar in the progress cell - """ - - def __init__(self, parent, queue): - QItemDelegate.__init__(self, parent) - self.queue = queue - - def paint(self, painter, option, index): - """ - paint the progressbar - """ - if not index.isValid(): - return - if index.column() == 5: - 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 is 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/module/gui/SettingsWidget.py b/module/gui/SettingsWidget.py deleted file mode 100644 index 4e8440667..000000000 --- a/module/gui/SettingsWidget.py +++ /dev/null @@ -1,202 +0,0 @@ -# -*- 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.sections and self.psections: - self.data = self.connector.getConfig() - self.pdata = self.connector.getPluginConfig() - - self.reloadSection(self.sections, self.data) - self.reloadSection(self.psections, self.pdata) - - return - - 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) - - general = QTabWidget() - self.general = general - - plugins = QTabWidget() - self.plugins = plugins - - tab = QTabWidget() - self.tab = tab - - gw = QWidget() - gw.setLayout(QVBoxLayout()) - gw.layout().addWidget(self.general) - pw = QWidget() - pw.setLayout(QVBoxLayout()) - pw.layout().addWidget(self.plugins) - tab.addTab(gw, _("General")) - tab.addTab(pw, _("Plugins")) - - layout.addWidget(tab) - - self.data = self.connector.getConfig() - self.pdata = self.connector.getPluginConfig() - for k, section in self.data.iteritems(): - s = Section(section, general) - self.sections[k] = s - - for k, section in self.pdata.iteritems(): - s = Section(section, plugins, "plugin") - self.psections[k] = s - - rel = QPushButton(_("Reload")) - save = QPushButton(_("Save")) - - layout.addWidget(save) - - cont = QHBoxLayout() - cont.addWidget(rel) - cont.addWidget(save) - - layout.addLayout(cont) - - self.connect(save, SIGNAL("clicked()"), self.saveConfig) - self.connect(rel, SIGNAL("clicked()"), self.loadConfig) - - def clearConfig(self): - self.sections = {} - - def reloadSection(self, sections, pdata): - - for k, section in enumerate(pdata): - if k in sections: - widget = sections[k] - for item in section.items: - if item.name in widget.inputs: - i = widget.inputs[item.name] - - if item.type == "int": - i.setValue(int(item.value)) - elif not item.type.find(";") == -1: - i.setCurrentIndex(i.findText(item.value)) - elif item.type == "bool": - if True if item.value.lower() in ("1", "true", "on", "an", "yes") else False: - i.setCurrentIndex(0) - else: - i.setCurrentIndex(1) - else: - i.setText(item.value) - - - def saveConfig(self): - self.data = self.connector.getConfig() - self.pdata = self.connector.getPluginConfig() - - self.saveSection(self.sections, self.data) - self.saveSection(self.psections, self.pdata, "plugin") - - - def saveSection(self, sections, pdata, sec="core"): - for k, section in enumerate(pdata): - if k in sections: - widget = sections[k] - for item in section.items: - if item.name in widget.inputs: - i = widget.inputs[item.name] - - #TODO: unresolved reference: option - - if item.type == "int": - if i.value() != int(item.value): - self.connector.setConfigValue(k, option, i.value(), sec) - elif not item.type.find(";") == -1: - if i.currentText() != item.value: - self.connector.setConfigValue(k, option, i.currentText(), sec) - elif item.type == "bool": - if (True if item.value.lower() in ("1", "true", "on", "an", "yes") else False) ^ (not i.currentIndex()): - self.connector.setConfigValue(k, option, not i.currentIndex(), sec) - else: - if i.text() != item.value: - self.connector.setConfigValue(k, option, str(i.text()), sec) - -class Section(QGroupBox): - def __init__(self, data, parent, ctype="core"): - self.data = data - QGroupBox.__init__(self, data.description, parent) - self.labels = {} - self.inputs = {} - self.ctype = ctype - layout = QFormLayout(self) - self.setLayout(layout) - - sw = QWidget() - sw.setLayout(QVBoxLayout()) - sw.layout().addWidget(self) - - sa = QScrollArea() - sa.setWidgetResizable(True) - sa.setWidget(sw) - sa.setFrameShape(sa.NoFrame) - - parent.addTab(sa, data.description) - - for option in self.data.items: - 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 True if option.value.lower() in ("1", "true", "on", "an", "yes") else False: - i.setCurrentIndex(0) - else: - i.setCurrentIndex(1) - else: - i = QLineEdit(self) - i.setText(option.value) - layout.addRow(option.description, i) - layout.setFieldGrowthPolicy(QFormLayout.AllNonFixedFieldsGrow) diff --git a/module/gui/XMLParser.py b/module/gui/XMLParser.py deleted file mode 100644 index d9adc74f6..000000000 --- a/module/gui/XMLParser.py +++ /dev/null @@ -1,71 +0,0 @@ -# -*- 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/module/gui/__init__.py b/module/gui/__init__.py deleted file mode 100644 index 8b1378917..000000000 --- a/module/gui/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/module/gui/connector.py b/module/gui/connector.py deleted file mode 100644 index c96389e91..000000000 --- a/module/gui/connector.py +++ /dev/null @@ -1,165 +0,0 @@ -# -*- 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.9" - -from time import sleep -from uuid import uuid4 as uuid - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -import socket - -from module.remote.thriftbackend.ThriftClient import ThriftClient, WrongLogin, NoSSL, NoConnection -from thrift.Thrift import TException - -class Connector(QObject): - """ - manages the connection to the pyload core via thrift - """ - - firstAttempt = True - - def __init__(self): - QObject.__init__(self) - self.mutex = QMutex() - self.connectionID = None - self.host = None - self.port = None - self.user = None - self.password = None - self.ssl = None - self.running = True - self.internal = False - self.proxy = self.Dummy() - - def setConnectionData(self, host, port, user, password, ssl=False): - """ - set connection data for connection attempt, called from slotConnect - """ - self.host = host - self.port = port - self.user = user - self.password = password - self.ssl = ssl - - def connectProxy(self): - """ - initialize thrift rpc client, - check for ssl, check auth, - setup dispatcher, - connect error signals, - check server version - """ - if self.internal: return True - - err = None - try: - client = ThriftClient(self.host, self.port, self.user, self.password) - except WrongLogin: - err = _("bad login credentials") - except NoSSL: - err = _("no ssl support") - except NoConnection: - err = _("can't connect to host") - if err: - if not Connector.firstAttempt: - self.emit(SIGNAL("errorBox"), err) - Connector.firstAttempt = False - return False - - self.proxy = DispatchRPC(self.mutex, client) - self.connect(self.proxy, SIGNAL("connectionLost"), self, SIGNAL("connectionLost")) - - server_version = self.proxy.getServerVersion() - self.connectionID = uuid().hex - - if not server_version == SERVER_VERSION: - self.emit(SIGNAL("errorBox"), _("server is version %(new)s client accepts version %(current)s") % {"new": server_version, "current": SERVER_VERSION}) - return False - - return True - - def __getattr__(self, attr): - """ - redirect rpc calls to dispatcher - """ - return getattr(self.proxy, attr) - - class Dummy(object): - """ - dummy rpc proxy, to prevent errors - """ - def __nonzero__(self): - return False - - def __getattr__(self, attr): - def dummy(*args, **kwargs): - return None - return dummy - -class DispatchRPC(QObject): - """ - wraps the thrift client, to catch critical exceptions (connection lost) - adds thread safety - """ - - def __init__(self, mutex, server): - QObject.__init__(self) - self.mutex = mutex - self.server = server - - def __getattr__(self, attr): - """ - redirect and wrap call in Wrapper instance, locks dispatcher - """ - self.mutex.lock() - self.fname = attr - f = self.Wrapper(getattr(self.server, attr), self.mutex, self) - return f - - class Wrapper(object): - """ - represents a rpc call - """ - - def __init__(self, f, mutex, dispatcher): - self.f = f - self.mutex = mutex - self.dispatcher = dispatcher - - def __call__(self, *args, **kwargs): - """ - instance is called, rpc is executed - exceptions are processed - finally dispatcher is unlocked - """ - lost = False - try: - return self.f(*args, **kwargs) - except socket.error: #necessary? - lost = True - except TException: - lost = True - finally: - self.mutex.unlock() - if lost: - from traceback import print_exc - print_exc() - self.dispatcher.emit(SIGNAL("connectionLost")) diff --git a/module/setup.py b/module/setup.py index 0127b629a..937ca5395 100644 --- a/module/setup.py +++ b/module/setup.py @@ -63,7 +63,7 @@ class Setup(): print _("When you are ready for system check, hit enter.") raw_input() - basic, ssl, captcha, gui, web, js = self.system_check() + basic, ssl, captcha, web, js = self.system_check() print "" if not basic: @@ -79,12 +79,16 @@ class Setup(): print "" avail = [] - if self.check_module("Crypto"): avail.append(_("container decrypting")) - if ssl: avail.append(_("ssl connection")) - if captcha: avail.append(_("automatic captcha decryption")) - if gui: avail.append(_("GUI")) - if web: avail.append(_("Webinterface")) - if js: avail.append(_("extended Click'N'Load")) + if self.check_module("Crypto"): + avail.append(_("container decrypting")) + if ssl: + avail.append(_("ssl connection")) + if captcha: + avail.append(_("automatic captcha decryption")) + if web: + avail.append(_("Webinterface")) + if js: + avail.append(_("extended Click'N'Load")) string = "" @@ -114,11 +118,6 @@ class Setup(): print _("Only needed for some hosters and as freeuser.") print "" - if not gui: - print _("Gui not available") - print _("The Graphical User Interface.") - print "" - if not js: print _("no JavaScript engine found") print _("You will need this for some Click'N'Load links. Install Spidermonkey, ossp-js, pyv8 or rhino") @@ -214,10 +213,6 @@ class Setup(): print "" - gui = self.check_module("PyQt4") - self.print_dep("PyQt4", gui) - - print "" jinja = True try: @@ -247,7 +242,7 @@ class Setup(): js = True if JsEngine.ENGINE else False self.print_dep(_("JS engine"), js) - return basic, ssl, captcha, gui, web, js + return basic, ssl, captcha, web, js def conf_basic(self): @@ -255,7 +250,7 @@ class Setup(): print _("## Basic Setup ##") print "" - print _("The following logindata is valid for CLI, GUI and webinterface.") + print _("The following logindata is valid for CLI and webinterface.") from module.database import DatabaseBackend diff --git a/pavement.py b/pavement.py index 6016ab4e0..3f8d61d75 100644 --- a/pavement.py +++ b/pavement.py @@ -208,11 +208,10 @@ def compile_js(): def generate_locale(): """ Generates localisation files """ - EXCLUDE = ["BeautifulSoup.py", "module/gui", "module/cli", "web/locale", "web/ajax", "web/cnl", "web/pyload", + EXCLUDE = ["BeautifulSoup.py", "module/cli", "web/locale", "web/ajax", "web/cnl", "web/pyload", "setup.py"] makepot("core", path("module"), EXCLUDE, "./pyLoadCore.py\n") - makepot("gui", path("module") / "gui", [], includes="./pyLoadGui.py\n") makepot("cli", path("module") / "cli", [], includes="./pyLoadCli.py\n") makepot("setup", "", [], includes="./module/setup.py\n") diff --git a/pyLoadCore.py b/pyLoadCore.py index e648e7fe9..7aec7aa4c 100755 --- a/pyLoadCore.py +++ b/pyLoadCore.py @@ -69,7 +69,6 @@ class Core(object): def __init__(self): self.doDebug = False - self.startedInGui = False self.running = False self.daemon = False self.remote = True diff --git a/pyLoadGui.py b/pyLoadGui.py deleted file mode 100755 index 69df22a4f..000000000 --- a/pyLoadGui.py +++ /dev/null @@ -1,764 +0,0 @@ -#!/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 -""" - -import sys - -from uuid import uuid4 as uuid # should be above PyQt imports -from time import sleep, time - -from base64 import b64decode - -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -import re -import module.common.pylgettext as gettext -import os -from os.path import abspath -from os.path import join -from os.path import basename -from os.path import commonprefix - -from module import InitHomeDir -from module.gui.ConnectionManager import * -from module.gui.Connector import Connector -from module.gui.MainWindow import * -from module.gui.Queue import * -from module.gui.Overview import * -from module.gui.Collector import * -from module.gui.XMLParser import * -from module.gui.CoreConfigParser import ConfigParser - -from module.lib.rename_process import renameProcess -from module.utils import formatSize, formatSpeed - -try: - import pynotify -except ImportError: - print "pynotify not installed, falling back to qt tray notification" - -class main(QObject): - def __init__(self): - """ - main setup - """ - QObject.__init__(self) - self.app = QApplication(sys.argv) - self.path = pypath - self.homedir = abspath("") - - self.configdir = "" - - self.init(True) - - 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() - - gettext.setpaths([join(os.sep, "usr", "share", "pyload", "locale"), None]) - translation = gettext.translation("pyLoadGui", join(pypath, "locale"), languages=[str(lang), "en"], fallback=True) - 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 - self.serverStatus = {"freespace":0} - - self.core = None # pyLoadCore if started - self.connectionLost = False - - if True: # when used if first, minimizing not working correctly.. - 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.slotQuit) - 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.connectProxy(): - self.init() - return - self.connect(self.connector, SIGNAL("connectionLost"), self.slotConnectionLost) - 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"), self.slotConnectionLost) - self.mainloop.stop() - self.mainWindow.saveWindow() - self.mainWindow.hide() - self.queue.stop() - - def connectSignals(self): - """ - signal and slot stuff, yay! - """ - self.connect(self.connector, SIGNAL("errorBox"), 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("refreshStatus"), self.slotRefreshStatus) - self.connect(self.mainWindow, SIGNAL("reloadAccounts"), self.slotReloadAccounts) - self.connect(self.mainWindow, SIGNAL("Quit"), self.slotQuit) - - self.connect(self.mainWindow.mactions["exit"], SIGNAL("triggered()"), self.slotQuit) - 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.quitInternal() - self.stopMain() - self.init() - - #def quit(self): #not used anymore? - # """ - # 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.connect(self.queue, SIGNAL("updateCount"), self.slotUpdateCount) - overview = self.mainWindow.tabs["overview"]["view"].model() - overview.queue = self.queue - self.connect(self.queue, SIGNAL("updateCount"), overview.queueChanged) - self.queue.start() - - def slotUpdateCount(self, pc, fc): - self.mainWindow.packageCount.setText("%i" % pc) - self.mainWindow.fileCount.setText("%i" % fc) - - def refreshServerStatus(self): - """ - refresh server status and overall speed in the status bar - """ - s = self.connector.statusServer() - if s.pause: - self.mainWindow.status.setText(_("paused")) - else: - self.mainWindow.status.setText(_("running")) - self.mainWindow.speed.setText(formatSpeed(s.speed)) - self.mainWindow.space.setText(formatSize(self.serverStatus["freespace"])) - self.mainWindow.actions["toggle_status"].setChecked(not s.pause) - - 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["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("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 - if internal, start pyLoadCore - set up connector, show main window - """ - self.connWindow.hide() - if data["type"] not in ("remote","internal"): - - coreparser = ConfigParser(self.configdir) - if not coreparser.config: - self.connector.setConnectionData("127.0.0.1", 7227, "anonymous", "anonymous", False) - else: - self.connector.setConnectionData("127.0.0.1", coreparser.get("remote","port"), "anonymous", "anonymous") - - elif data["type"] == "remote": - self.connector.setConnectionData(data["host"], data["port"], data["user"], data["password"]) - - elif data["type"] == "internal": - from pyLoadCore import Core - from module.ConfigParser import ConfigParser as CoreConfig - import thread - - if not self.core: - - config = CoreConfig() #create so at least default config exists - self.core = Core() - self.core.startedInGui = True - thread.start_new_thread(self.core.start, (False, False)) - while not self.core.running: - sleep(0.5) - - self.connector.proxy = self.core.api - self.connector.internal = True - - #self.connector.setConnectionData("127.0.0.1", config.get("remote","port"), "anonymous", "anonymous") - - self.startMain() -# try: -# host = data["host"] -# except: -# host = "127.0.0.1" - - 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 - """ - if status: - self.connector.unpauseServer() - else: - self.connector.pauseServer() - - def slotAddPackage(self, name, links, password=None): - """ - emitted from main window - add package to the collector - """ - pack = self.connector.addPackage(name, links, Destination.Collector) - if password: - data = {"password": password} - self.connector.setPackageData(pack, data) - - def slotAddFileToPackage(self, pid, fid): #TODO deprecated? gets called - """ - emitted from collector view after a drop action - """ - #self.connector.addFileToPackage(fid, pid) - pass - - 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.uploadContainer(filename, 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.pushToQueue(id) - - def slotRestartDownload(self, id, isPack): - """ - emitted from main window - restart download - """ - if isPack: - self.connector.restartPackage(id) - else: - self.connector.restartFile(id) - - def slotRefreshStatus(self, id): - """ - emitted from main window - refresh download status - """ - self.connector.recheckPackage(id) - - def slotRemoveDownload(self, id, isPack): - """ - emitted from main window - remove download - """ - if isPack: - self.connector.deletePackages([id]) - else: - self.connector.deleteFiles([id]) - - def slotAbortDownload(self, id, isPack): - """ - emitted from main window - remove download - """ - if isPack: - data = self.connector.getFileOrder(id) #less data to transmit - self.connector.stopDownloads(data.values()) - else: - self.connector.stopDownloads([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|ftp)://[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2, 5}(([0-9]{1, 5})?/.*)?") - matches = pattern.finditer(text) - - # thanks to: jmansour //#139 - links = [str(match.group(0)) for match in matches] - if len(links) == 0: - return - - filenames = [link.rpartition("/")[2] for link in links] - - packagename = commonprefix(filenames) - if len(packagename) == 0: - packagename = filenames[0] - - self.slotAddPackage(packagename, links) - - 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.pullFromQueue(pid) - - def checkCaptcha(self): - if self.connector.isCaptchaWaiting() and self.mainWindow.captchaDock.isFree(): - t = self.connector.getCaptchaTask(False) - self.mainWindow.show() - self.mainWindow.raise_() - self.mainWindow.activateWindow() - self.mainWindow.captchaDock.emit(SIGNAL("setTask"), t.tid, b64decode(t.data), t.type) - elif not self.mainWindow.captchaDock.isFree(): - status = self.connector.getCaptchaTaskStatus(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(cid, str(result)) - - def pullEvents(self): - events = self.connector.getEvents(self.connector.connectionID) - if not events: - return - for event in events: - if event.eventname == "account": - self.mainWindow.emit(SIGNAL("reloadAccounts"), False) - elif event.eventname == "config": - pass - elif event.destination == Destination.Queue: - self.queue.addEvent(event) - try: - if event.eventname == "update" and event.type == ElementType.File: - info = self.connector.getFileData(event.id) - if info.statusmsg == "finished": - self.emit(SIGNAL("showMessage"), _("Finished downloading of '%s'") % info.name) - elif info.statusmsg == "failed": - self.emit(SIGNAL("showMessage"), _("Failed downloading '%s'!") % info.name) - if event.event == "insert" and event.type == ElementType.File: - info = self.connector.getLinkInfo(event[3]) - self.emit(SIGNAL("showMessage"), _("Added '%s' to queue") % info.name) - except: - print "can't send notification" - elif event.destination == Destination.Collector: - self.packageCollector.addEvent(event) - - def slotReloadAccounts(self, force=False): - self.mainWindow.tabs["accounts"]["view"].model().reloadData(force) - - def slotQuit(self): - self.tray.hide() - self.quitInternal() - self.app.quit() - - def quitInternal(self): - if self.core: - self.core.api.kill() - for i in range(10): - if self.core.shuttedDown: - break - sleep(0.5) - - def slotConnectionLost(self): - if not self.connectionLost: - self.connectionLost = True - m = QMessageBox(QMessageBox.Critical, _("Connection lost"), _("Lost connection to the core!"), QMessageBox.Ok) - m.exec_() - self.slotQuit() - - class Loop(): - def __init__(self, parent): - self.parent = parent - self.timer = QTimer() - self.timer.connect(self.timer, SIGNAL("timeout()"), self.update) - self.lastSpaceCheck = 0 - - def start(self): - self.update() - self.timer.start(1000) - - def update(self): - """ - methods to call - """ - self.parent.refreshServerStatus() - if self.lastSpaceCheck + 5 < time(): - self.lastSpaceCheck = time() - self.parent.serverStatus["freespace"] = self.parent.connector.freeSpace() - 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(pypath, "icons", "logo-gui.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(pypath, "icons", "close.png")), _("Exit"), self.contextMenu) - self.contextMenu.addAction(self.exitAction) - self.setContextMenu(self.contextMenu) - - self.connect(self, SIGNAL("activated(QSystemTrayIcon::ActivationReason)"), self.clicked) - - def mainWindowHidden(self): - self.showAction.setChecked(False) - - def clicked(self, reason): - if self.showAction.isEnabled(): - if reason == QSystemTrayIcon.Trigger: - 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: - print "init error" - - def showMessage(self, body): - if self.usePynotify: - n = pynotify.Notification("pyload", body, join(pypath, "icons", "logo.png")) - try: - n.set_hint_string("x-canonical-append", "") - except: - pass - n.show() - else: - self.tray.showMessage("pyload", body) - -if __name__ == "__main__": - renameProcess('pyLoadGui') - app = main() - app.loop() diff --git a/icons/pyload2.ico b/pyload.ico Binary files differindex c2b497986..c2b497986 100644 --- a/icons/pyload2.ico +++ b/pyload.ico diff --git a/systemCheck.py b/systemCheck.py index a1f8ba67f..05bcc9f79 100644 --- a/systemCheck.py +++ b/systemCheck.py @@ -37,12 +37,6 @@ def main(): except: print("image libary:", "missing") - try: - import PyQt4.QtCore - print("pyqt:", PyQt4.QtCore.PYQT_VERSION_STR) - except: - print("pyqt:", "missing") - print("\n\n##### System Status #####") print("\n## pyLoadCore ##") @@ -93,22 +87,6 @@ def main(): for line in core_info: print(line) - print("\n## pyLoadGui ##") - - gui_err = [] - - try: - import PyQt4 - except: - gui_err.append("GUI won't work without pyqt4 !!") - - if gui_err: - print("The system check has detected some errors:\n") - for err in gui_err: - print(err) - else: - print("No Problems detected, pyLoadGui should work fine.") - print("\n## Webinterface ##") web_err = [] |