WebBrowser/PersonalInformationManager/PersonalInformationManager.py

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

eric ide

mercurial