|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 from PyQt4.QtCore import Qt, QObject |
|
7 from PyQt4.QtGui import QDialog, QMenu |
|
8 |
|
9 from .PersonalDataDialog import PersonalDataDialog |
|
10 |
|
11 import Preferences |
|
12 import UI.PixmapCache |
|
13 |
|
14 |
|
15 class PersonalInformationManager(QObject): |
|
16 """ |
|
17 Class implementing the personal information manager used to complete form fields. |
|
18 """ |
|
19 FullName = 0 |
|
20 LastName = 1 |
|
21 FirstName = 2 |
|
22 Email = 3 |
|
23 Mobile = 4 |
|
24 Phone = 5 |
|
25 Address = 6 |
|
26 City = 7 |
|
27 Zip = 8 |
|
28 State = 9 |
|
29 Country = 10 |
|
30 HomePage = 11 |
|
31 Special1 = 12 |
|
32 Special2 = 13 |
|
33 Special3 = 14 |
|
34 Special4 = 15 |
|
35 Max = 16 |
|
36 Invalid = 256 |
|
37 |
|
38 def __init__(self, parent=None): |
|
39 """ |
|
40 Constructor |
|
41 |
|
42 @param parent reference to the parent object (QObject) |
|
43 """ |
|
44 super().__init__(parent) |
|
45 |
|
46 self.__loaded = False |
|
47 self.__allInfo = {} |
|
48 self.__infoMatches = {} |
|
49 self.__translations = {} |
|
50 |
|
51 self.__view = None |
|
52 self.__element = None |
|
53 |
|
54 def __loadSettings(self): |
|
55 """ |
|
56 Private method to load the settings. |
|
57 """ |
|
58 self.__allInfo[self.FullName] = Preferences.getHelp("PimFullName") |
|
59 self.__allInfo[self.LastName] = Preferences.getHelp("PimLastName") |
|
60 self.__allInfo[self.FirstName] = Preferences.getHelp("PimFirstName") |
|
61 self.__allInfo[self.Email] = Preferences.getHelp("PimEmail") |
|
62 self.__allInfo[self.Mobile] = Preferences.getHelp("PimMobile") |
|
63 self.__allInfo[self.Phone] = Preferences.getHelp("PimPhone") |
|
64 self.__allInfo[self.Address] = Preferences.getHelp("PimAddress") |
|
65 self.__allInfo[self.City] = Preferences.getHelp("PimCity") |
|
66 self.__allInfo[self.Zip] = Preferences.getHelp("PimZip") |
|
67 self.__allInfo[self.State] = Preferences.getHelp("PimState") |
|
68 self.__allInfo[self.Country] = Preferences.getHelp("PimCountry") |
|
69 self.__allInfo[self.HomePage] = Preferences.getHelp("PimHomePage") |
|
70 self.__allInfo[self.Special1] = Preferences.getHelp("PimSpecial1") |
|
71 self.__allInfo[self.Special2] = Preferences.getHelp("PimSpecial2") |
|
72 self.__allInfo[self.Special3] = Preferences.getHelp("PimSpecial3") |
|
73 self.__allInfo[self.Special4] = Preferences.getHelp("PimSpecial4") |
|
74 |
|
75 self.__translations[self.FullName] = self.trUtf8("Full Name") |
|
76 self.__translations[self.LastName] = self.trUtf8("Last Name") |
|
77 self.__translations[self.FirstName] = self.trUtf8("First Name") |
|
78 self.__translations[self.Email] = self.trUtf8("E-mail") |
|
79 self.__translations[self.Mobile] = self.trUtf8("Mobile") |
|
80 self.__translations[self.Phone] = self.trUtf8("Phone") |
|
81 self.__translations[self.Address] = self.trUtf8("Address") |
|
82 self.__translations[self.City] = self.trUtf8("City") |
|
83 self.__translations[self.Zip] = self.trUtf8("ZIP Code") |
|
84 self.__translations[self.State] = self.trUtf8("State/Region") |
|
85 self.__translations[self.Country] = self.trUtf8("Country") |
|
86 self.__translations[self.HomePage] = self.trUtf8("Home Page") |
|
87 self.__translations[self.Special1] = self.trUtf8("Custom 1") |
|
88 self.__translations[self.Special2] = self.trUtf8("Custom 2") |
|
89 self.__translations[self.Special3] = self.trUtf8("Custom 3") |
|
90 self.__translations[self.Special4] = self.trUtf8("Custom 4") |
|
91 |
|
92 self.__infoMatches[self.FullName] = ["fullname", "realname"] |
|
93 self.__infoMatches[self.LastName] = ["lastname", "surname"] |
|
94 self.__infoMatches[self.FirstName] = ["firstname", "name"] |
|
95 self.__infoMatches[self.Email] = ["email", "e-mail", "mail"] |
|
96 self.__infoMatches[self.Mobile] = ["mobile", "mobilephone"] |
|
97 self.__infoMatches[self.Phone] = ["phone", "telephone"] |
|
98 self.__infoMatches[self.Address] = ["address"] |
|
99 self.__infoMatches[self.City] = ["city"] |
|
100 self.__infoMatches[self.Zip] = ["zip"] |
|
101 self.__infoMatches[self.State] = ["state", "region"] |
|
102 self.__infoMatches[self.Country] = ["country"] |
|
103 self.__infoMatches[self.HomePage] = ["homepage", "www"] |
|
104 |
|
105 self.__loaded = True |
|
106 |
|
107 def showConfigurationDialog(self): |
|
108 """ |
|
109 Public method to show the configuration dialog. |
|
110 """ |
|
111 dlg = PersonalDataDialog() |
|
112 if dlg.exec_() == QDialog.Accepted: |
|
113 dlg.storeData() |
|
114 self.__loadSettings() |
|
115 |
|
116 def createSubMenu(self, menu, view, hitTestResult): |
|
117 """ |
|
118 Public method to create the personal information sub-menu. |
|
119 |
|
120 @param menu reference to the main menu (QMenu) |
|
121 @param view reference to the view (HelpBrowser) |
|
122 @param hitTestResult reference to the hit test result (QWebHitTestResult) |
|
123 """ |
|
124 self.__view = view |
|
125 self.__element = hitTestResult.element() |
|
126 |
|
127 if not hitTestResult.isContentEditable(): |
|
128 return |
|
129 |
|
130 if not self.__loaded: |
|
131 self.__loadSettings() |
|
132 |
|
133 submenu = QMenu(self.trUtf8("Insert Personal Information"), menu) |
|
134 submenu.setIcon(UI.PixmapCache.getIcon("pim.png")) |
|
135 |
|
136 for key, info in sorted(self.__allInfo.items()): |
|
137 if info: |
|
138 act = submenu.addAction(self.__translations[key], self.__insertData) |
|
139 act.setData(info) |
|
140 |
|
141 submenu.addSeparator() |
|
142 submenu.addAction(self.trUtf8("Edit Personal Information"), |
|
143 self.showConfigurationDialog) |
|
144 |
|
145 menu.addMenu(submenu) |
|
146 menu.addSeparator() |
|
147 |
|
148 def __insertData(self): |
|
149 """ |
|
150 Private slot to insert the selected personal information. |
|
151 """ |
|
152 act = self.sender() |
|
153 if not self.__element or self.__element.isNull() or act is None: |
|
154 return |
|
155 |
|
156 info = act.data() |
|
157 info = info.replace('"', '\\"') |
|
158 self.__element.evaluateJavaScript( |
|
159 'var newVal = this.value.substring(0, this.selectionStart) + "{0}" +' |
|
160 ' this.value.substring(this.selectionEnd); this.value = newVal;'.format(info)) |
|
161 |
|
162 def viewKeyPressEvent(self, view, evt): |
|
163 """ |
|
164 Public method to handle key press events we are interested in. |
|
165 |
|
166 @param view reference to the view (HelpBrowser) |
|
167 @param evt reference to the key event (QKeyEvent) |
|
168 @return flag indicating handling of the event (boolean) |
|
169 """ |
|
170 if view is None: |
|
171 return False |
|
172 |
|
173 isEnter = evt.key() in [Qt.Key_Return, Qt.Key_Enter] |
|
174 if not isEnter or evt.modifiers() != Qt.ControlModifier: |
|
175 return False |
|
176 |
|
177 if not self.__loaded: |
|
178 self.__loadSettings() |
|
179 |
|
180 document = view.page().mainFrame().documentElement() |
|
181 elements = document.findAll('input[type="text"]') |
|
182 |
|
183 for element in elements: |
|
184 name = element.attribute("name") |
|
185 if name == "": |
|
186 continue |
|
187 |
|
188 match = self.__nameMatch(name) |
|
189 if match != self.Invalid: |
|
190 element.evaluateJavaScript( |
|
191 'this.value = "{0}"'.format(self.__allInfo[match])) |
|
192 |
|
193 return True |
|
194 |
|
195 def __nameMatch(self, name): |
|
196 """ |
|
197 Private method to find the information entry for the given field. |
|
198 |
|
199 @param name name of the form field (string) |
|
200 @return value of the information entry (integer) |
|
201 """ |
|
202 for index in range(self.Max): |
|
203 if self.__allInfo[index]: |
|
204 for n in self.__infoMatches[index]: |
|
205 if name == n or n in name: |
|
206 return index |
|
207 |
|
208 return self.Invalid |
|
209 |
|
210 def connectPage(self, page): |
|
211 """ |
|
212 Public method to allow the personal information manager to connect to the page. |
|
213 |
|
214 @param page reference to the web page (HelpWebPage) |
|
215 """ |
|
216 page.loadFinished.connect(self.__pageLoadFinished) |
|
217 |
|
218 def __pageLoadFinished(self, ok): |
|
219 """ |
|
220 Private slot to handle the completion of a page load. |
|
221 |
|
222 @param ok flag indicating a successful load (boolean) |
|
223 """ |
|
224 page = self.sender() |
|
225 if page is None or not ok: |
|
226 return |
|
227 |
|
228 if not self.__loaded: |
|
229 self.__loadSettings() |
|
230 |
|
231 document = page.mainFrame().documentElement() |
|
232 elements = document.findAll('input[type="text"]') |
|
233 |
|
234 for element in elements: |
|
235 name = element.attribute("name") |
|
236 if name == "": |
|
237 continue |
|
238 |
|
239 match = self.__nameMatch(name) |
|
240 if match != self.Invalid: |
|
241 element.setStyleProperty( |
|
242 "-webkit-appearance", "none") |
|
243 element.setStyleProperty( |
|
244 "-webkit-box-shadow", "inset 0 0 2px 1px #0000EE") |