eric6/WebBrowser/PersonalInformationManager/PersonalInformationManager.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a personal information manager used to complete form
8 fields.
9 """
10
11 from __future__ import unicode_literals
12
13 from PyQt5.QtCore import Qt, QObject, QPoint
14 from PyQt5.QtWidgets import QDialog, QMenu
15
16 import Preferences
17 import UI.PixmapCache
18
19 from ..WebBrowserPage import WebBrowserPage
20
21
22 class PersonalInformationManager(QObject):
23 """
24 Class implementing the personal information manager used to complete form
25 fields.
26 """
27 FullName = 0
28 LastName = 1
29 FirstName = 2
30 Email = 3
31 Mobile = 4
32 Phone = 5
33 Address = 6
34 City = 7
35 Zip = 8
36 State = 9
37 Country = 10
38 HomePage = 11
39 Special1 = 12
40 Special2 = 13
41 Special3 = 14
42 Special4 = 15
43 Max = 16
44 Invalid = 256
45
46 def __init__(self, parent=None):
47 """
48 Constructor
49
50 @param parent reference to the parent object (QObject)
51 """
52 super(PersonalInformationManager, self).__init__(parent)
53
54 self.__loaded = False
55 self.__allInfo = {}
56 self.__infoMatches = {}
57 self.__translations = {}
58
59 self.__view = None
60 self.__clickedPos = QPoint()
61
62 def __loadSettings(self):
63 """
64 Private method to load the settings.
65 """
66 self.__allInfo[self.FullName] = \
67 Preferences.getWebBrowser("PimFullName")
68 self.__allInfo[self.LastName] = \
69 Preferences.getWebBrowser("PimLastName")
70 self.__allInfo[self.FirstName] = \
71 Preferences.getWebBrowser("PimFirstName")
72 self.__allInfo[self.Email] = Preferences.getWebBrowser("PimEmail")
73 self.__allInfo[self.Mobile] = Preferences.getWebBrowser("PimMobile")
74 self.__allInfo[self.Phone] = Preferences.getWebBrowser("PimPhone")
75 self.__allInfo[self.Address] = Preferences.getWebBrowser("PimAddress")
76 self.__allInfo[self.City] = Preferences.getWebBrowser("PimCity")
77 self.__allInfo[self.Zip] = Preferences.getWebBrowser("PimZip")
78 self.__allInfo[self.State] = Preferences.getWebBrowser("PimState")
79 self.__allInfo[self.Country] = Preferences.getWebBrowser("PimCountry")
80 self.__allInfo[self.HomePage] = \
81 Preferences.getWebBrowser("PimHomePage")
82 self.__allInfo[self.Special1] = \
83 Preferences.getWebBrowser("PimSpecial1")
84 self.__allInfo[self.Special2] = \
85 Preferences.getWebBrowser("PimSpecial2")
86 self.__allInfo[self.Special3] = \
87 Preferences.getWebBrowser("PimSpecial3")
88 self.__allInfo[self.Special4] = \
89 Preferences.getWebBrowser("PimSpecial4")
90
91 self.__translations[self.FullName] = self.tr("Full Name")
92 self.__translations[self.LastName] = self.tr("Last Name")
93 self.__translations[self.FirstName] = self.tr("First Name")
94 self.__translations[self.Email] = self.tr("E-mail")
95 self.__translations[self.Mobile] = self.tr("Mobile")
96 self.__translations[self.Phone] = self.tr("Phone")
97 self.__translations[self.Address] = self.tr("Address")
98 self.__translations[self.City] = self.tr("City")
99 self.__translations[self.Zip] = self.tr("ZIP Code")
100 self.__translations[self.State] = self.tr("State/Region")
101 self.__translations[self.Country] = self.tr("Country")
102 self.__translations[self.HomePage] = self.tr("Home Page")
103 self.__translations[self.Special1] = self.tr("Custom 1")
104 self.__translations[self.Special2] = self.tr("Custom 2")
105 self.__translations[self.Special3] = self.tr("Custom 3")
106 self.__translations[self.Special4] = self.tr("Custom 4")
107
108 self.__infoMatches[self.FullName] = ["fullname", "realname"]
109 self.__infoMatches[self.LastName] = ["lastname", "surname"]
110 self.__infoMatches[self.FirstName] = ["firstname", "name"]
111 self.__infoMatches[self.Email] = ["email", "e-mail", "mail"]
112 self.__infoMatches[self.Mobile] = ["mobile", "mobilephone"]
113 self.__infoMatches[self.Phone] = ["phone", "telephone"]
114 self.__infoMatches[self.Address] = ["address"]
115 self.__infoMatches[self.City] = ["city"]
116 self.__infoMatches[self.Zip] = ["zip"]
117 self.__infoMatches[self.State] = ["state", "region"]
118 self.__infoMatches[self.Country] = ["country"]
119 self.__infoMatches[self.HomePage] = ["homepage", "www"]
120
121 self.__loaded = True
122
123 def showConfigurationDialog(self):
124 """
125 Public method to show the configuration dialog.
126 """
127 from .PersonalDataDialog import PersonalDataDialog
128 dlg = PersonalDataDialog()
129 if dlg.exec_() == QDialog.Accepted:
130 dlg.storeData()
131 self.__loadSettings()
132
133 def createSubMenu(self, menu, view, hitTestResult):
134 """
135 Public method to create the personal information sub-menu.
136
137 @param menu reference to the main menu (QMenu)
138 @param view reference to the view (HelpBrowser)
139 @param hitTestResult reference to the hit test result
140 (WebHitTestResult)
141 """
142 self.__view = view
143 self.__clickedPos = hitTestResult.pos()
144
145 if not hitTestResult.isContentEditable():
146 return
147
148 if not self.__loaded:
149 self.__loadSettings()
150
151 submenu = QMenu(self.tr("Insert Personal Information"), menu)
152 submenu.setIcon(UI.PixmapCache.getIcon("pim.png"))
153
154 for key, info in sorted(self.__allInfo.items()):
155 if info:
156 act = submenu.addAction(self.__translations[key])
157 act.setData(info)
158 act.triggered.connect(lambda: self.__insertData(act))
159
160 submenu.addSeparator()
161 submenu.addAction(self.tr("Edit Personal Information"),
162 self.showConfigurationDialog)
163
164 menu.addMenu(submenu)
165 menu.addSeparator()
166
167 def __insertData(self, act):
168 """
169 Private slot to insert the selected personal information.
170
171 @param act reference to the action that triggered
172 @type QAction
173 """
174 if self.__view is None or self.__clickedPos.isNull():
175 return
176
177 info = act.data()
178 info = info.replace('"', '\\"')
179
180 source = """
181 var e = document.elementFromPoint({0}, {1});
182 if (e) {{
183 var v = e.value.substring(0, e.selectionStart);
184 v += "{2}" + e.value.substring(e.selectionEnd);
185 e.value = v;
186 }}""".format(self.__clickedPos.x(), self.__clickedPos.y(), info)
187 self.__view.page().runJavaScript(source, WebBrowserPage.SafeJsWorld)
188
189 def viewKeyPressEvent(self, view, evt):
190 """
191 Protected method to handle key press events we are interested in.
192
193 @param view reference to the view (HelpBrowser)
194 @param evt reference to the key event (QKeyEvent)
195 @return flag indicating handling of the event (boolean)
196 """
197 if view is None:
198 return False
199
200 isEnter = evt.key() in [Qt.Key_Return, Qt.Key_Enter]
201 isControlModifier = evt.modifiers() & Qt.ControlModifier
202 if not isEnter or not isControlModifier:
203 return False
204
205 if not self.__loaded:
206 self.__loadSettings()
207
208 source = """
209 var inputs = document.getElementsByTagName('input');
210 var table = {0};
211 for (var i = 0; i < inputs.length; ++i) {{
212 var input = inputs[i];
213 if (input.type != 'text' || input.name == '')
214 continue;
215 for (var key in table) {{
216 if (!table.hasOwnProperty(key))
217 continue;
218 if (key == input.name || input.name.indexOf(key) != -1) {{
219 input.value = table[key];
220 break;
221 }}
222 }}
223 }}""".format(self.__matchingJsTable())
224 view.page().runJavaScript(source, WebBrowserPage.SafeJsWorld)
225
226 return True
227
228 def connectPage(self, page):
229 """
230 Public method to allow the personal information manager to connect to
231 the page.
232
233 @param page reference to the web page
234 @type WebBrowserPage
235 """
236 page.loadFinished.connect(lambda ok: self.__pageLoadFinished(ok, page))
237
238 def __pageLoadFinished(self, ok, page):
239 """
240 Private slot to handle the completion of a page load.
241
242 @param ok flag indicating a successful load
243 @type bool
244 @param page reference to the web page object
245 @type WebBrowserPage
246 """
247 if page is None or not ok:
248 return
249
250 if not self.__loaded:
251 self.__loadSettings()
252
253 source = """
254 var inputs = document.getElementsByTagName('input');
255 var table = {0};
256 for (var i = 0; i < inputs.length; ++i) {{
257 var input = inputs[i];
258 if (input.type != 'text' || input.name == '')
259 continue;
260 for (var key in table) {{
261 if (!table.hasOwnProperty(key) || table[key] == '')
262 continue;
263 if (key == input.name || input.name.indexOf(key) != -1) {{
264 input.style['-webkit-appearance'] = 'none';
265 input.style['-webkit-box-shadow'] =
266 'inset 0 0 2px 1px #000EEE';
267 break;
268 }}
269 }}
270 }}""".format(self.__matchingJsTable())
271 page.runJavaScript(source, WebBrowserPage.SafeJsWorld)
272
273 def __matchingJsTable(self):
274 """
275 Private method to create the common part of the JavaScript sources.
276
277 @return JavaScript source
278 @rtype str
279 """
280 values = []
281 for key, names in self.__infoMatches.items():
282 for name in names:
283 value = self.__allInfo[key].replace('"', '\\"')
284 values.append('"{0}":"{1}"'.format(name, value))
285 return "{{ {0} }}".format(",".join(values))

eric ide

mercurial