src/eric7/WebBrowser/PersonalInformationManager/PersonalInformationManager.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
equal deleted inserted replaced
9208:3fc8dfeb6ebe 9209:b99e7fd55fd3
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 - 2022 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 import functools
12
13 from PyQt6.QtCore import Qt, QObject, QPoint
14 from PyQt6.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().__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] = Preferences.getWebBrowser(
67 "PimFullName")
68 self.__allInfo[self.LastName] = Preferences.getWebBrowser(
69 "PimLastName")
70 self.__allInfo[self.FirstName] = Preferences.getWebBrowser(
71 "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] = Preferences.getWebBrowser(
81 "PimHomePage")
82 self.__allInfo[self.Special1] = Preferences.getWebBrowser(
83 "PimSpecial1")
84 self.__allInfo[self.Special2] = Preferences.getWebBrowser(
85 "PimSpecial2")
86 self.__allInfo[self.Special3] = Preferences.getWebBrowser(
87 "PimSpecial3")
88 self.__allInfo[self.Special4] = Preferences.getWebBrowser(
89 "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.DialogCode.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"))
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(
159 functools.partial(self.__insertData, act))
160
161 submenu.addSeparator()
162 submenu.addAction(self.tr("Edit Personal Information"),
163 self.showConfigurationDialog)
164
165 menu.addMenu(submenu)
166 menu.addSeparator()
167
168 def __insertData(self, act):
169 """
170 Private slot to insert the selected personal information.
171
172 @param act reference to the action that triggered
173 @type QAction
174 """
175 if self.__view is None or self.__clickedPos.isNull():
176 return
177
178 info = act.data()
179 info = info.replace('"', '\\"')
180
181 source = """
182 var e = document.elementFromPoint({0}, {1});
183 if (e) {{
184 var v = e.value.substring(0, e.selectionStart);
185 v += "{2}" + e.value.substring(e.selectionEnd);
186 e.value = v;
187 }}""".format(self.__clickedPos.x(), self.__clickedPos.y(), info)
188 self.__view.page().runJavaScript(source, WebBrowserPage.SafeJsWorld)
189
190 def viewKeyPressEvent(self, view, evt):
191 """
192 Protected method to handle key press events we are interested in.
193
194 @param view reference to the view (HelpBrowser)
195 @param evt reference to the key event (QKeyEvent)
196 @return flag indicating handling of the event (boolean)
197 """
198 if view is None:
199 return False
200
201 isEnter = evt.key() in [Qt.Key.Key_Return, Qt.Key.Key_Enter]
202 isControlModifier = (
203 evt.modifiers() & Qt.KeyboardModifier.ControlModifier
204 )
205 if not isEnter or not isControlModifier:
206 return False
207
208 if not self.__loaded:
209 self.__loadSettings()
210
211 source = """
212 var inputs = document.getElementsByTagName('input');
213 var table = {0};
214 for (var i = 0; i < inputs.length; ++i) {{
215 var input = inputs[i];
216 if (input.type != 'text' || input.name == '')
217 continue;
218 for (var key in table) {{
219 if (!table.hasOwnProperty(key))
220 continue;
221 if (key == input.name || input.name.indexOf(key) != -1) {{
222 input.value = table[key];
223 break;
224 }}
225 }}
226 }}""".format(self.__matchingJsTable())
227 view.page().runJavaScript(source, WebBrowserPage.SafeJsWorld)
228
229 return True
230
231 def connectPage(self, page):
232 """
233 Public method to allow the personal information manager to connect to
234 the page.
235
236 @param page reference to the web page
237 @type WebBrowserPage
238 """
239 page.loadFinished.connect(lambda ok: self.__pageLoadFinished(ok, page))
240
241 def __pageLoadFinished(self, ok, page):
242 """
243 Private slot to handle the completion of a page load.
244
245 @param ok flag indicating a successful load
246 @type bool
247 @param page reference to the web page object
248 @type WebBrowserPage
249 """
250 if page is None or not ok:
251 return
252
253 if not self.__loaded:
254 self.__loadSettings()
255
256 source = """
257 var inputs = document.getElementsByTagName('input');
258 var table = {0};
259 for (var i = 0; i < inputs.length; ++i) {{
260 var input = inputs[i];
261 if (input.type != 'text' || input.name == '')
262 continue;
263 for (var key in table) {{
264 if (!table.hasOwnProperty(key) || table[key] == '')
265 continue;
266 if (key == input.name || input.name.indexOf(key) != -1) {{
267 input.style['-webkit-appearance'] = 'none';
268 input.style['-webkit-box-shadow'] =
269 'inset 0 0 2px 1px #000EEE';
270 break;
271 }}
272 }}
273 }}""".format(self.__matchingJsTable())
274 page.runJavaScript(source, WebBrowserPage.SafeJsWorld)
275
276 def __matchingJsTable(self):
277 """
278 Private method to create the common part of the JavaScript sources.
279
280 @return JavaScript source
281 @rtype str
282 """
283 values = []
284 for key, names in self.__infoMatches.items():
285 for name in names:
286 value = self.__allInfo[key].replace('"', '\\"')
287 values.append('"{0}":"{1}"'.format(name, value))
288 return "{{ {0} }}".format(",".join(values))

eric ide

mercurial