~stomato463/+junk/nvdajp

« back to all changes in this revision

Viewing changes to source/gui/__init__.py

  • Committer: Masataka Shinke
  • Date: 2011-10-25 12:35:26 UTC
  • mfrom: (4185 jpmain)
  • mto: This revision was merged to the branch mainline in revision 4211.
  • Revision ID: mshinke@users.sourceforge.jp-20111025123526-ze527a2rl3z0g2ky
lp:~nishimotz/nvdajp/main : 4185 をマージ

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#gui/__init__.py
2
2
#A part of NonVisual Desktop Access (NVDA)
3
 
#Copyright (C) 2006-2007 NVDA Contributors <http://www.nvda-project.org/>
 
3
#Copyright (C) 2006-2011 NVDA Contributors <http://www.nvda-project.org/>
4
4
#This file is covered by the GNU General Public License.
5
5
#See the file COPYING for more details.
6
6
 
8
8
import os
9
9
import sys
10
10
import wx
11
 
from wx.lib import newevent
12
11
import globalVars
13
12
import ui
14
13
from logHandler import log
26
25
import api
27
26
 
28
27
### Constants
29
 
appTitle = "NVDA"
30
28
NVDA_PATH = os.getcwdu()
31
 
ICON_PATH=os.path.join(NVDA_PATH, "images", "nvda.ico")
32
 
 
33
 
ExternalCommandEvent, evt_externalCommand = newevent.NewCommandEvent()
34
 
id_showGuiCommand=wx.NewId()
35
 
evtid_externalExecute = wx.NewEventType()
36
 
evt_externalExecute = wx.PyEventBinder(evtid_externalExecute, 1)
 
29
ICON_PATH=os.path.join(NVDA_PATH, "images", "nvdajp.ico")
37
30
 
38
31
### Globals
39
32
mainFrame = None
40
 
isExitDialog=False
41
 
#: A list of top level windows excluding L{mainFrame} which are currently instantiated and which should be destroyed on exit.
42
 
 
43
 
class ExternalExecuteEvent(wx.PyCommandEvent):
44
 
        def __init__(self, func, args, kwargs, callback):
45
 
                super(ExternalExecuteEvent, self).__init__(evtid_externalExecute, wx.ID_ANY)
46
 
                self._func = func
47
 
                self._args = args
48
 
                self._kwargs = kwargs
49
 
                self._callback = callback
50
 
 
51
 
        def run(self):
52
 
                ret = self._func(*self._args, **self._kwargs)
53
 
                if self._callback:
54
 
                        queueHandler.registerGeneratorObject(self._callback_gen(ret))
55
 
 
56
 
        def _callback_gen(self, ret):
57
 
                for n in xrange(20):
58
 
                        yield None
59
 
                self._callback(ret)
 
33
isInMessageBox = False
60
34
 
61
35
def getDocFilePath(fileName, localized=True):
62
36
        if not getDocFilePath.rootPath:
100
74
 
101
75
        def __init__(self):
102
76
                style = wx.DEFAULT_FRAME_STYLE ^ wx.MAXIMIZE_BOX ^ wx.MINIMIZE_BOX | wx.FRAME_NO_TASKBAR
103
 
                super(MainFrame, self).__init__(None, wx.ID_ANY, appTitle, size=(1,1), style=style)
 
77
                super(MainFrame, self).__init__(None, wx.ID_ANY, versionInfo.name, size=(1,1), style=style)
104
78
                self.Bind(wx.EVT_CLOSE, self.onExitCommand)
105
 
                self.Bind(evt_externalCommand, self.onExitCommand, id=wx.ID_EXIT)
106
 
                self.Bind(evt_externalCommand, self.onShowGuiCommand, id=id_showGuiCommand)
107
 
                self.Bind(evt_externalExecute,lambda evt: evt.run())
108
79
                self.sysTrayIcon = SysTrayIcon(self)
109
80
                # This makes Windows return to the previous foreground window and also seems to allow NVDA to be brought to the foreground.
110
81
                self.Show()
111
82
                self.Hide()
 
83
                if winUser.isWindowVisible(self.Handle):
 
84
                        # HACK: Work around a wx bug where Hide() doesn't actually hide the window,
 
85
                        # but IsShown() returns False and Hide() again doesn't fix it.
 
86
                        # This seems to happen if the call takes too long.
 
87
                        self.Show()
 
88
                        self.Hide()
112
89
 
113
90
        def Destroy(self):
114
91
                self.sysTrayIcon.Destroy()
134
111
                        self.Show()
135
112
                        self.Hide()
136
113
 
137
 
        def onShowGuiCommand(self,evt):
 
114
        def showGui(self):
138
115
                # The menu pops up at the location of the mouse, which means it pops up at an unpredictable location.
139
116
                # Therefore, move the mouse to the centre of the screen so that the menu will always pop up there.
140
117
                left, top, width, height = api.getDesktopObject().location
148
125
                queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("configuration applied"))
149
126
 
150
127
        def onSaveConfigurationCommand(self,evt):
 
128
                if globalVars.appArgs.secure:
 
129
                        queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("Cannot save configuration - NVDA in secure mode"))
 
130
                        return
151
131
                try:
152
132
                        config.save()
153
133
                        queueHandler.queueFunction(queueHandler.eventQueue,ui.message,_("configuration saved"))
154
134
                except:
155
 
                        self.prePopup()
156
 
                        d = wx.MessageDialog(self,_("Could not save configuration - probably read only file system"),_("Error"),style=wx.OK | wx.ICON_ERROR)
157
 
                        d.ShowModal()
158
 
                        d.Destroy()
159
 
                        self.postPopup()
 
135
                        messageBox(_("Could not save configuration - probably read only file system"),_("Error"),wx.OK | wx.ICON_ERROR)
160
136
 
161
137
        def _popupSettingsDialog(self, dialog, *args, **kwargs):
 
138
                if isInMessageBox:
 
139
                        return
162
140
                self.prePopup()
163
 
                dialog(self, *args, **kwargs).Show()
 
141
                try:
 
142
                        dialog(self, *args, **kwargs).Show()
 
143
                except SettingsDialog.MultiInstanceError:
 
144
                        messageBox(_("Please close  the other NVDA settings dialog first"),_("Error"),style=wx.OK | wx.ICON_ERROR)
164
145
                self.postPopup()
165
146
 
166
147
        def onDefaultDictionaryCommand(self,evt):
173
154
                self._popupSettingsDialog(DictionaryDialog,_("Temporary dictionary"),speechDictHandler.dictionaries["temp"])
174
155
 
175
156
        def onExitCommand(self, evt):
176
 
                global isExitDialog
177
157
                canExit=False
178
158
                if config.conf["general"]["askToExit"]:
179
 
                        self.prePopup()
180
 
                        isExitDialog=True
181
 
                        d = wx.MessageDialog(self, _("Are you sure you want to quit NVDA?"), _("Exit NVDA"), wx.YES|wx.NO|wx.ICON_WARNING)
182
 
                        if d.ShowModal() == wx.ID_YES:
 
159
                        if isInMessageBox:
 
160
                                return
 
161
                        if messageBox(_("Are you sure you want to quit NVDA?"), _("Exit NVDA"), wx.YES_NO|wx.ICON_WARNING) == wx.YES:
183
162
                                canExit=True
184
 
                        isExitDialog=False
185
 
                        d.Destroy()
186
 
                        self.postPopup()
187
163
                else:
188
164
                        canExit=True
189
165
                if canExit:
213
189
        def onObjectPresentationCommand(self,evt):
214
190
                self._popupSettingsDialog(ObjectPresentationDialog)
215
191
 
216
 
        def onVirtualBuffersCommand(self,evt):
217
 
                self._popupSettingsDialog(VirtualBuffersDialog)
 
192
        def onBrowseModeCommand(self,evt):
 
193
                self._popupSettingsDialog(BrowseModeDialog)
218
194
 
219
195
        def onDocumentFormattingCommand(self,evt):
220
196
                self._popupSettingsDialog(DocumentFormattingDialog)
221
197
 
 
198
        def onSpeechSymbolsCommand(self, evt):
 
199
                self._popupSettingsDialog(SpeechSymbolsDialog)
 
200
 
222
201
        def onAboutCommand(self,evt):
223
 
                try:
224
 
                        aboutInfo="""%s
225
 
%s: %s
226
 
%s: %s
227
 
%s: %s"""%(versionInfo.longName,_("version"),versionInfo.version,_("url"),versionInfo.url,_("copyright"),versionInfo.copyrightInfo)
228
 
                        self.prePopup()
229
 
                        d = wx.MessageDialog(self, aboutInfo, _("About NVDA"), wx.OK)
230
 
                        d.ShowModal()
231
 
                        d.Destroy()
232
 
                        self.postPopup()
233
 
                except:
234
 
                        log.error("gui.mainFrame.onAbout", exc_info=True)
 
202
                messageBox(versionInfo.aboutMessage, _("About NVDA"), wx.OK)
235
203
 
236
204
        def onViewLogCommand(self, evt):
237
205
                logViewer.activate()
250
218
                        pythonConsole.initialize()
251
219
                pythonConsole.activate()
252
220
 
 
221
        def onReloadPluginsCommand(self, evt):
 
222
                import appModuleHandler, globalPluginHandler
 
223
                from NVDAObjects import NVDAObject
 
224
                appModuleHandler.reloadAppModules()
 
225
                globalPluginHandler.reloadGlobalPlugins()
 
226
                NVDAObject.clearDynamicClassCache()
 
227
 
253
228
class SysTrayIcon(wx.TaskBarIcon):
254
229
 
255
230
        def __init__(self, frame):
256
231
                super(SysTrayIcon, self).__init__()
257
232
                icon=wx.Icon(ICON_PATH,wx.BITMAP_TYPE_ICO)
258
 
                self.SetIcon(icon, appTitle)
 
233
                self.SetIcon(icon, versionInfo.name)
259
234
 
260
235
                self.menu=wx.Menu()
261
236
                menu_preferences=wx.Menu()
271
246
                self.Bind(wx.EVT_MENU, frame.onKeyboardSettingsCommand, item)
272
247
                item = menu_preferences.Append(wx.ID_ANY, _("&Mouse settings..."),_("Change reporting of mouse shape and object under mouse"))
273
248
                self.Bind(wx.EVT_MENU, frame.onMouseSettingsCommand, item)
274
 
                item = menu_preferences.Append(wx.ID_ANY,_("&Review cursor..."),_("Configure how and when the review cursor moves"))
 
249
                item = menu_preferences.Append(wx.ID_ANY,_("Review &cursor..."),_("Configure how and when the review cursor moves")) 
275
250
                self.Bind(wx.EVT_MENU, frame.onReviewCursorCommand, item)
276
 
                item = menu_preferences.Append(wx.ID_ANY,_("&Object presentation..."),_("Change reporting of objects"))
 
251
                item = menu_preferences.Append(wx.ID_ANY,_("&Object presentation..."),_("Change reporting of objects")) 
277
252
                self.Bind(wx.EVT_MENU, frame.onObjectPresentationCommand, item)
278
 
                item = menu_preferences.Append(wx.ID_ANY,_("Virtual &buffers..."),_("Change virtual buffers specific settings"))
279
 
                self.Bind(wx.EVT_MENU, frame.onVirtualBuffersCommand, item)
280
 
                item = menu_preferences.Append(wx.ID_ANY,_("Document &formatting..."),_("Change Settings of document properties"))
 
253
                item = menu_preferences.Append(wx.ID_ANY,_("&Browse mode..."),_("Change virtual buffers specific settings")) 
 
254
                self.Bind(wx.EVT_MENU, frame.onBrowseModeCommand, item)
 
255
                item = menu_preferences.Append(wx.ID_ANY,_("Document &formatting..."),_("Change Settings of document properties")) 
281
256
                self.Bind(wx.EVT_MENU, frame.onDocumentFormattingCommand, item)
282
257
                subMenu_speechDicts = wx.Menu()
283
 
                item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Default dictionary..."),_("dialog where you can set default dictionary by adding dictionary entries to the list"))
284
 
                self.Bind(wx.EVT_MENU, frame.onDefaultDictionaryCommand, item)
285
 
                item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Voice dictionary..."),_("dialog where you can set voice-specific dictionary by adding dictionary entries to the list"))
286
 
                self.Bind(wx.EVT_MENU, frame.onVoiceDictionaryCommand, item)
 
258
                if not globalVars.appArgs.secure:
 
259
                        item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Default dictionary..."),_("dialog where you can set default dictionary by adding dictionary entries to the list"))
 
260
                        self.Bind(wx.EVT_MENU, frame.onDefaultDictionaryCommand, item)
 
261
                        item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Voice dictionary..."),_("dialog where you can set voice-specific dictionary by adding dictionary entries to the list"))
 
262
                        self.Bind(wx.EVT_MENU, frame.onVoiceDictionaryCommand, item)
287
263
                item = subMenu_speechDicts.Append(wx.ID_ANY,_("&Temporary dictionary..."),_("dialog where you can set temporary dictionary by adding dictionary entries to the edit box"))
288
264
                self.Bind(wx.EVT_MENU, frame.onTemporaryDictionaryCommand, item)
289
265
                menu_preferences.AppendMenu(wx.ID_ANY,_("Speech &dictionaries"),subMenu_speechDicts)
 
266
                if not globalVars.appArgs.secure:
 
267
                        item = menu_preferences.Append(wx.ID_ANY, _("&Punctuation/symbol pronunciation..."))
 
268
                        self.Bind(wx.EVT_MENU, frame.onSpeechSymbolsCommand, item)
290
269
                self.menu.AppendMenu(wx.ID_ANY,_("&Preferences"),menu_preferences)
291
270
 
292
271
                menu_tools = wx.Menu()
298
277
                if not globalVars.appArgs.secure:
299
278
                        item = menu_tools.Append(wx.ID_ANY, _("Python console"))
300
279
                        self.Bind(wx.EVT_MENU, frame.onPythonConsoleCommand, item)
 
280
                item = menu_tools.Append(wx.ID_ANY, _("Reload plugins"))
 
281
                self.Bind(wx.EVT_MENU, frame.onReloadPluginsCommand, item)
301
282
                self.menu.AppendMenu(wx.ID_ANY, _("Tools"), menu_tools)
302
283
 
303
284
                menu_help = wx.Menu()
304
285
                if not globalVars.appArgs.secure:
305
286
                        item = menu_help.Append(wx.ID_ANY, _("User guide"))
306
287
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("userGuide.html")), item)
307
 
                        item = menu_help.Append(wx.ID_ANY, _("Key Command Quick Reference"))
308
 
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("key commands.txt")), item)
 
288
                        item = menu_help.Append(wx.ID_ANY, _("Keyboard Command Quick Reference"))
 
289
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("keyCommands.html")), item)
309
290
                        item = menu_help.Append(wx.ID_ANY, _("What's &new"))
310
291
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("changes.html")), item)
311
292
                        item = menu_help.Append(wx.ID_ANY, _("Web site"))
312
 
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile("http://www.nvda-project.org/"), item)
313
 
                        item = menu_help.Append(wx.ID_ANY, _("Readme"))
314
 
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("readme.txt")), item)
 
293
                        # self.Bind(wx.EVT_MENU, lambda evt: os.startfile("http://www.nvda-project.org/"), item)
 
294
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile("http://sourceforge.jp/projects/nvdajp/"), item) #nvdajp
 
295
                        item = menu_help.Append(wx.ID_ANY, _("Readme")) #nvdajp
 
296
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("readme.txt")), item) #nvdajp
315
297
                        item = menu_help.Append(wx.ID_ANY, _("License"))
316
298
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("copying.txt", False)), item)
317
299
                        item = menu_help.Append(wx.ID_ANY, _("Contributors"))
318
 
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("contributors.txt", False)), item)
 
300
                        # self.Bind(wx.EVT_MENU, lambda evt: os.startfile(getDocFilePath("contributors.txt", False)), item)
 
301
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile("http://sourceforge.jp/projects/nvdajp/wiki/contributors_ja"), item) #nvdajp
319
302
                item = menu_help.Append(wx.ID_ANY, _("We&lcome dialog"))
320
303
                self.Bind(wx.EVT_MENU, lambda evt: WelcomeDialog.run(), item)
321
304
                menu_help.AppendSeparator()
325
308
                self.menu.AppendSeparator()
326
309
                item = self.menu.Append(wx.ID_ANY, _("&Revert to saved configuration"),_("Reset all settings to saved state"))
327
310
                self.Bind(wx.EVT_MENU, frame.onRevertToSavedConfigurationCommand, item)
328
 
                item = self.menu.Append(wx.ID_SAVE, _("&Save configuration"), _("Write the current configuration to nvda.ini"))
329
 
                self.Bind(wx.EVT_MENU, frame.onSaveConfigurationCommand, item)
 
311
                if not globalVars.appArgs.secure:
 
312
                        item = self.menu.Append(wx.ID_SAVE, _("&Save configuration"), _("Write the current configuration to nvda.ini"))
 
313
                        self.Bind(wx.EVT_MENU, frame.onSaveConfigurationCommand, item)
 
314
                if not globalVars.appArgs.secure:
 
315
                        self.menu.AppendSeparator()
 
316
                        item = self.menu.Append(wx.ID_ANY, _("Donate"))
 
317
                        self.Bind(wx.EVT_MENU, lambda evt: os.startfile("http://www.nvaccess.org/wiki/Donate"), item)
330
318
                self.menu.AppendSeparator()
331
319
                item = self.menu.Append(wx.ID_EXIT, _("E&xit"),_("Exit NVDA"))
332
320
                self.Bind(wx.EVT_MENU, frame.onExitCommand, item)
352
340
        mainFrame.Destroy()
353
341
 
354
342
def showGui():
355
 
        wx.PostEvent(mainFrame, ExternalCommandEvent(id_showGuiCommand))
 
343
        wx.CallAfter(mainFrame.showGui)
356
344
 
357
345
def quit():
358
 
        global isExitDialog
359
 
        if not isExitDialog:
360
 
                wx.PostEvent(mainFrame, ExternalCommandEvent(wx.ID_EXIT))
361
 
 
362
 
def execute(func, callback=None, *args, **kwargs):
363
 
        """Execute a function in the GUI thread.
364
 
        This should be used when scripts need to interact with the user via the GUI.
365
 
        For example, a frame or dialog can be created and this function can then be used to execute its Show method.
366
 
        @param func: The function to execute.
367
 
        @type func: callable
368
 
        @param callback: A function to call in the main thread when C{func} returns. The function will be passed the return value as its only argument.
 
346
        wx.CallAfter(mainFrame.onExitCommand, None)
 
347
 
 
348
def messageBox(message, caption=wx.MessageBoxCaptionStr, style=wx.OK | wx.CENTER, parent=None):
 
349
        """Display a message dialog.
 
350
        This should be used for all message dialogs
 
351
        rather than using C{wx.MessageDialog} and C{wx.MessageBox} directly.
 
352
        @param message: The message text.
 
353
        @type message: str
 
354
        @param caption: The caption (title) of the dialog.
 
355
        @type caption: str
 
356
        @param style: Same as for wx.MessageBox.
 
357
        @type style: int
 
358
        @param parent: The parent window (optional).
 
359
        @type parent: C{wx.Window}
 
360
        @return: Same as for wx.MessageBox.
 
361
        @rtype: int
 
362
        """
 
363
        global isInMessageBox
 
364
        wasAlready = isInMessageBox
 
365
        isInMessageBox = True
 
366
        if not parent:
 
367
                mainFrame.prePopup()
 
368
        res = wx.MessageBox(message, caption, style, parent or mainFrame)
 
369
        if not parent:
 
370
                mainFrame.postPopup()
 
371
        if not wasAlready:
 
372
                isInMessageBox = False
 
373
        return res
 
374
 
 
375
def runScriptModalDialog(dialog, callback=None):
 
376
        """Run a modal dialog from a script.
 
377
        This will not block the caller,
 
378
        but will instead call C{callback} (if provided) with the result from the dialog.
 
379
        The dialog will be destroyed once the callback has returned.
 
380
        @param dialog: The dialog to show.
 
381
        @type dialog: C{wx.Dialog}
 
382
        @param callback: The optional callable to call with the result from the dialog.
369
383
        @type callback: callable
370
 
        @param args: Arguments for the function.
371
 
        @param kwargs: Keyword arguments for the function.
372
 
"""
373
 
        wx.PostEvent(mainFrame, ExternalExecuteEvent(func, args, kwargs, callback))
 
384
        """
 
385
        def run():
 
386
                mainFrame.prePopup()
 
387
                res = dialog.ShowModal()
 
388
                mainFrame.postPopup()
 
389
                if callback:
 
390
                        callback(res)
 
391
                dialog.Destroy()
 
392
        wx.CallAfter(run)
374
393
 
375
394
class WelcomeDialog(wx.Dialog):
376
395
        """The NVDA welcome dialog.
400
419
                self.nconvAsNVDAModifierCheckBox = wx.CheckBox(self, wx.ID_ANY, _("Use NonConvert as an NVDA modifier key")) #nvdajp
401
420
                self.nconvAsNVDAModifierCheckBox.SetValue(config.conf["keyboard"]["useNonConvertAsNVDAModifierKey"])
402
421
                optionsSizer.Add(self.nconvAsNVDAModifierCheckBox,flag=wx.TOP|wx.RIGHT,border=10)
 
422
                #nvdajp done
403
423
                self.showWelcomeDialogAtStartupCheckBox = wx.CheckBox(self, wx.ID_ANY, _("Show this dialog when NVDA starts"))
404
424
                self.showWelcomeDialogAtStartupCheckBox.SetValue(config.conf["general"]["showWelcomeDialogAtStartup"])
405
425
                optionsSizer.Add(self.showWelcomeDialogAtStartupCheckBox,flag=wx.TOP|wx.LEFT,border=10)
437
457
        This dialog tells the user that their configuration file is broken.
438
458
        """
439
459
 
440
 
        MESSAGE=_("""Your configuration file contains errors.
 
460
        MESSAGE=_("""Your configuration file contains errors. 
441
461
Press 'Ok' to fix these errors, or press 'Cancel' if you wish to manually edit your config file at a later stage to make corrections. More details about the errors can be found in the log file.
442
462
""")
443
463