1# -*- coding: utf-8 -*-
2
3# Copyright (c) 2012 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4#
5
6"""
7Module implementing the GreaseMonkey scripts configuration dialog.
8"""
9
10from PyQt5.QtCore import pyqtSlot, Qt, QUrl
11from PyQt5.QtGui import QDesktopServices
12from PyQt5.QtWidgets import QDialog, QListWidgetItem
13
14from E5Gui import E5MessageBox
15
16from .Ui_GreaseMonkeyConfigurationDialog import (
17    Ui_GreaseMonkeyConfigurationDialog
18)
19
20import UI.PixmapCache
21
22
23class GreaseMonkeyConfigurationDialog(
24        QDialog, Ui_GreaseMonkeyConfigurationDialog):
25    """
26    Class implementing the GreaseMonkey scripts configuration dialog.
27    """
28    ScriptVersionRole = Qt.ItemDataRole.UserRole
29    ScriptDescriptionRole = Qt.ItemDataRole.UserRole + 1
30    ScriptRole = Qt.ItemDataRole.UserRole + 2
31
32    def __init__(self, manager, parent=None):
33        """
34        Constructor
35
36        @param manager reference to the manager object (GreaseMonkeyManager)
37        @param parent reference to the parent widget (QWidget)
38        """
39        super().__init__(parent)
40        self.setupUi(self)
41        self.setWindowFlags(Qt.WindowType.Window)
42
43        self.iconLabel.setPixmap(
44            UI.PixmapCache.getPixmap("greaseMonkey48"))
45
46        self.__manager = manager
47
48        self.__loadScripts()
49
50        self.scriptsList.removeItemRequested.connect(self.__removeItem)
51        self.scriptsList.itemChanged.connect(self.__itemChanged)
52
53    @pyqtSlot()
54    def on_openDirectoryButton_clicked(self):
55        """
56        Private slot to open the GreaseMonkey scripts directory.
57        """
58        QDesktopServices.openUrl(
59            QUrl.fromLocalFile(self.__manager.scriptsDirectory()))
60
61    @pyqtSlot(str)
62    def on_downloadLabel_linkActivated(self, link):
63        """
64        Private slot to open the greasyfork.org web site.
65
66        @param link URL (string)
67        """
68        from WebBrowser.WebBrowserWindow import WebBrowserWindow
69        if not link or "userscript.org" in link:
70            # userscript.org is down, default to Greasy Fork.
71            link = "https://greasyfork.org/"
72        WebBrowserWindow.mainWindow().newTab(QUrl(link))
73        self.close()
74
75    @pyqtSlot(QListWidgetItem)
76    def on_scriptsList_itemDoubleClicked(self, item):
77        """
78        Private slot to show information about the selected script.
79
80        @param item reference to the double clicked item (QListWidgetItem)
81        """
82        script = self.__getScript(item)
83        if script is not None:
84            from .GreaseMonkeyConfigurationScriptInfoDialog import (
85                GreaseMonkeyConfigurationScriptInfoDialog
86            )
87            infoDlg = GreaseMonkeyConfigurationScriptInfoDialog(script, self)
88            infoDlg.exec()
89
90    def __loadScripts(self):
91        """
92        Private method to load all the available scripts.
93        """
94        for script in self.__manager.allScripts():
95            itm = QListWidgetItem(self.scriptsList)
96            itm.setText(script.name())
97            icon = script.icon()
98            if icon.isNull:
99                icon = UI.PixmapCache.getIcon("greaseMonkeyScript")
100            itm.setIcon(icon)
101            itm.setData(
102                GreaseMonkeyConfigurationDialog.ScriptVersionRole,
103                script.version())
104            itm.setData(
105                GreaseMonkeyConfigurationDialog.ScriptDescriptionRole,
106                script.description())
107            itm.setFlags(itm.flags() | Qt.ItemFlag.ItemIsUserCheckable)
108            if script.isEnabled():
109                itm.setCheckState(Qt.CheckState.Checked)
110            else:
111                itm.setCheckState(Qt.CheckState.Unchecked)
112            itm.setData(GreaseMonkeyConfigurationDialog.ScriptRole, script)
113            self.scriptsList.addItem(itm)
114
115        self.scriptsList.sortItems()
116
117        itemMoved = True
118        while itemMoved:
119            itemMoved = False
120            for row in range(self.scriptsList.count()):
121                topItem = self.scriptsList.item(row)
122                bottomItem = self.scriptsList.item(row + 1)
123                if topItem is None or bottomItem is None:
124                    continue
125
126                if (
127                    topItem.checkState() == Qt.CheckState.Unchecked and
128                    bottomItem.checkState == Qt.CheckState.Checked
129                ):
130                    itm = self.scriptsList.takeItem(row + 1)
131                    self.scriptsList.insertItem(row, itm)
132                    itemMoved = True
133
134    def __getScript(self, itm):
135        """
136        Private method to get the script for the given item.
137
138        @param itm item to get script for (QListWidgetItem)
139        @return reference to the script object (GreaseMonkeyScript)
140        """
141        if itm is None:
142            return None
143
144        script = itm.data(GreaseMonkeyConfigurationDialog.ScriptRole)
145        return script
146
147    def __removeItem(self, itm):
148        """
149        Private slot to remove a script item.
150
151        @param itm item to be removed (QListWidgetItem)
152        """
153        script = self.__getScript(itm)
154        if script is None:
155            return
156
157        removeIt = E5MessageBox.yesNo(
158            self,
159            self.tr("Remove Script"),
160            self.tr(
161                """<p>Are you sure you want to remove <b>{0}</b>?</p>""")
162            .format(script.name()))
163        if removeIt and self.__manager.removeScript(script):
164            self.scriptsList.takeItem(self.scriptsList.row(itm))
165            del itm
166
167    def __itemChanged(self, itm):
168        """
169        Private slot to handle changes of a script item.
170
171        @param itm changed item (QListWidgetItem)
172        """
173        script = self.__getScript(itm)
174        if script is None:
175            return
176
177        if itm.checkState() == Qt.CheckState.Checked:
178            self.__manager.enableScript(script)
179        else:
180            self.__manager.disableScript(script)
181