1 # -*- coding: UTF-8 -*-
2 # vim: expandtab sw=4 ts=4 sts=4:
5 Phone configuration wizard
7 __author__
= 'Michal Čihař'
8 __email__
= 'michal@cihar.com'
10 Copyright © 2003 - 2008 Michal Čihař
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License version 2 as published by
14 the Free Software Foundation.
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 import Wammu
.SettingsStorage
32 import Wammu
.PhoneSearch
35 import wx
.lib
.hyperlink
36 from Wammu
.Locales
import StrConv
38 class FinalPage(Wammu
.Wizard
.InputPage
):
40 Shows result of configuration, and allow to name phone.
42 def __init__(self
, parent
):
43 Wammu
.Wizard
.InputPage
.__init
__(self
, parent
,
44 _('Configuration done'),
45 _('Thank you for configuring phone connection.'),
46 parent
.settings
.GetName(),
47 _('You can enter any name which you will use to identify your phone.')
51 return Wammu
.Wizard
.InputPage
.GetNext(self
)
53 def Blocked(self
, evt
):
54 self
.parent
.settings
.SetName(self
.edit
.GetValue())
57 def Activated(self
, evt
):
58 self
.edit
.SetValue(self
.parent
.settings
.GetName())
60 class TestPage(Wammu
.Wizard
.SimplePage
):
62 Tests phone connection.
64 def __init__(self
, parent
):
65 Wammu
.Wizard
.SimplePage
.__init
__(self
, parent
, _('Connection test'))
66 self
.detail
= wx
.StaticText(
69 _('Wammu is now testing phone connection, please wait...'))
71 self
.sizer
.Add(self
.detail
, 0, wx
.ALL
, 5)
74 self
.Bind(Wammu
.Events
.EVT_DATA
, self
.OnSearchEnd
)
77 self
.parent
.pg_final
.SetPrev(self
)
78 return self
.parent
.pg_final
80 def Activated(self
, evt
):
81 if evt
.GetDirection():
83 _('Wammu is now testing phone connection, please wait...'))
84 device
= self
.parent
.settings
.GetPort()
85 connection
= self
.parent
.settings
.GetGammuDriver()
86 self
.thread
= Wammu
.PhoneSearch
.PhoneInfoThread(self
, device
, connection
)
90 def OnSearchEnd(self
, evt
):
93 self
.detail
.SetLabel('%s\n%s' % (
99 manuf
= evt
.data
['Manufacturer']
100 model
= evt
.data
['Model'][0]
101 self
.name
= '%s %s' % (manuf
, model
)
102 self
.parent
.settings
.SetName(self
.name
)
103 self
.detail
.SetLabel(
104 _('Phone has been found.') +
105 (_('Manufacturer: %(manufacturer)s\nModel: %(model)s') %
106 { 'manufacturer' : manuf
, 'model' : model
}))
107 self
.detail
.Wrap(400)
109 def Blocked(self
, evt
):
110 if self
.thread
is not None and self
.thread
.isAlive():
111 wx
.MessageDialog(self
,
112 _('Phone connection test is still active, you can not continue.'),
113 _('Testing still active!'),
114 wx
.OK | wx
.ICON_ERROR
).ShowModal()
116 if evt
.GetDirection() and self
.name
== '':
117 if wx
.MessageDialog(self
,
118 _('Phone has not been found, are you sure you want to continue?'),
119 _('Phone not found!'),
120 wx
.YES_NO | wx
.NO_DEFAULT | wx
.ICON_ERROR
).ShowModal() == wx
.ID_YES
:
125 def Cancel(self
, evt
):
126 # FIXME: we should abort test here
127 if self
.thread
is not None and self
.thread
.isAlive():
128 wx
.MessageDialog(self
,
129 _('Phone connection test is still active, you can not continue.'),
130 _('Testing still active!'),
131 wx
.OK | wx
.ICON_ERROR
).ShowModal()
135 class PhoneSearchPage(Wammu
.Wizard
.TextPage
):
139 def __init__(self
, parent
):
140 Wammu
.Wizard
.TextPage
.__init
__(self
, parent
,
142 _('Phone searching status') + ':')
143 self
.Bind(Wammu
.Events
.EVT_DONE
, self
.OnDone
)
144 self
.Bind(Wammu
.Events
.EVT_TEXT
, self
.OnText
)
145 self
.Bind(Wammu
.Events
.EVT_SHOW_MESSAGE
, self
.OnShowMessage
)
150 self
.parent
.pg_test
.SetPrev(self
)
151 return self
.parent
.pg_test
153 def Blocked(self
, evt
):
154 if self
.thread
is not None and self
.thread
.isAlive():
155 wx
.MessageDialog(self
,
156 _('Phone search is still active, you can not continue.'),
157 _('Searching still active!'),
158 wx
.OK | wx
.ICON_ERROR
).ShowModal()
160 if evt
.GetDirection() and len(self
.results
) == 0:
161 wx
.MessageDialog(self
,
162 _('No phone has not been found, you can not continue.'),
163 _('No phone found!'),
164 wx
.OK | wx
.ICON_ERROR
).ShowModal()
168 def Cancel(self
, evt
):
169 # FIXME: we should abort searching here
170 if self
.thread
is not None and self
.thread
.isAlive():
171 wx
.MessageDialog(self
,
172 _('Phone search is still active, you can not continue.'),
173 _('Searching still active!'),
174 wx
.OK | wx
.ICON_ERROR
).ShowModal()
178 def Activated(self
, evt
):
179 if evt
.GetDirection():
181 self
.edit
.AppendText(_('Wammu is now searching for phone:') + '\n')
182 self
.thread
= Wammu
.PhoneSearch
.AllSearchThread(
184 callback
= self
.SearchDone
,
185 msgcallback
= self
.SearchMessage
,
186 noticecallback
= self
.SearchNotice
,
187 limit
= self
.parent
.settings
.GetConnection(),
192 def SearchNotice(self
, title
, text
):
193 evt
= Wammu
.Events
.ShowMessageEvent(
196 type = wx
.ICON_WARNING
)
197 wx
.PostEvent(self
, evt
)
199 def SearchMessage(self
, text
):
201 This has to send message as it is called from different thread.
203 evt
= Wammu
.Events
.TextEvent(text
= text
+ '\n')
204 wx
.PostEvent(self
, evt
)
206 def SearchDone(self
, lst
):
208 This has to send message as it is called from different thread.
211 evt
= Wammu
.Events
.DoneEvent()
212 wx
.PostEvent(self
, evt
)
214 def OnText(self
, evt
):
215 self
.edit
.AppendText(StrConv(evt
.text
))
217 def OnShowMessage(self
, evt
):
218 wx
.MessageDialog(self
.parent
,
219 StrConv(evt
.message
),
221 wx
.OK | evt
.type).ShowModal()
223 def OnDone(self
, evt
):
225 Select one config to use.
227 if len(self
.results
) == 0:
228 self
.edit
.AppendText(_('No phone has been found!') + '\n')
230 if len(self
.results
) > 1:
231 # Allow user to select phone
232 # FIXME: Might be in wizard, but this should be rare...
234 for phone
in self
.results
:
236 _('Model %(model)s (%(manufacturer)s) on %(port)s port using connection %(connection)s') %
238 'model': phone
[2][0],
239 'manufacturer': phone
[3],
241 'connection': phone
[1]
243 dlg
= wx
.SingleChoiceDialog(self
, _('Select phone to use from bellow list'), _('Select phone'),
245 if dlg
.ShowModal() == wx
.ID_OK
:
246 idx
= dlg
.GetSelection()
247 config
= self
.results
[idx
]
252 # Use directly only found phone
253 config
= self
.results
[0]
255 if config
is not None:
256 self
.parent
.settings
.SetPort(config
[0])
257 self
.parent
.settings
.SetGammuDriver(config
[1])
258 self
.edit
.AppendText(_('Following phone will be used:') + '\n')
259 self
.edit
.AppendText(
260 _('Model %(model)s (%(manufacturer)s) on %(port)s port using connection %(connection)s') %
262 'model': config
[2][0],
263 'manufacturer': config
[3],
265 'connection': config
[1]
268 self
.edit
.AppendText(_('No phone selected!') + '\n')
271 class ManualPage(Wammu
.Wizard
.MultiInputPage
):
273 Manual phone configuration.
275 def __init__(self
, parent
):
276 Wammu
.Wizard
.MultiInputPage
.__init
__(self
, parent
,
277 _('Manual configuration'),
279 _('Port where phone is connected') + ':',
280 _('Connection type') + ':',
283 parent
.settings
.GetDevices()[0],
284 Wammu
.Data
.Connections
,
288 self
.parent
.settings
.SetPort(self
.edits
[0].GetValue())
289 self
.parent
.settings
.SetGammuDriver(self
.edits
[1].GetValue())
290 self
.parent
.pg_test
.SetPrev(self
)
291 return self
.parent
.pg_test
293 def Blocked(self
, evt
):
294 if evt
.GetDirection():
295 if self
.edits
[0].GetValue() == '':
296 wx
.MessageDialog(self
,
297 _('You need to select port which will be used.'),
298 _('No port selected!'),
299 wx
.OK | wx
.ICON_ERROR
).ShowModal()
301 if self
.edits
[1].GetValue() == '':
302 wx
.MessageDialog(self
,
303 _('You need to select connection type which will be used.'),
304 _('No connection selected!'),
305 wx
.OK | wx
.ICON_ERROR
).ShowModal()
309 class PhonePortPage(Wammu
.Wizard
.InputPage
):
313 def __init__(self
, parent
):
314 ports
, helptext
= parent
.settings
.GetDevices()
315 Wammu
.Wizard
.InputPage
.__init
__(self
, parent
,
317 _('Please enter port where phone is connected') + ':',
322 self
.parent
.settings
.SetPort(self
.edit
.GetValue())
323 self
.parent
.pg_test
.SetPrev(self
)
324 return self
.parent
.pg_test
326 def Blocked(self
, evt
):
327 if evt
.GetDirection() and self
.edit
.GetValue() == '':
328 wx
.MessageDialog(self
,
329 _('You need to select port which will be used.'),
330 _('No port selected!'),
331 wx
.OK | wx
.ICON_ERROR
).ShowModal()
335 class PhoneGammuDriverPage(Wammu
.Wizard
.ChoicePage
):
337 Selects real Gammu phone driver.
339 def __init__(self
, parent
):
340 self
.names
, connections
, helps
= parent
.settings
.GetGammuDrivers()
342 if len(self
.names
) == 0:
343 Wammu
.Wizard
.SimplePage
.__init
__(self
, parent
,
345 _('Sorry no driver matches your configuration, please return back and try different settings or manual configuration.'))
347 Wammu
.Wizard
.ChoicePage
.__init
__(self
, parent
,
351 extratext
= _('Please select which driver you want to use. Follow the help text shown bellow to select the best one.')
356 Dynamically create next page for current settings.
358 if len(self
.names
) == 0:
360 self
.parent
.settings
.SetGammuDriver(self
.names
[self
.GetType()])
361 next
= PhonePortPage(self
.parent
)
365 class PhoneDriverPage(Wammu
.Wizard
.ChoicePage
):
367 Selects Gammu phone driver type.
369 def __init__(self
, parent
):
370 self
.names
, connections
, helps
= parent
.settings
.GetDrivers()
372 Wammu
.Wizard
.ChoicePage
.__init
__(self
, parent
,
373 _('Connection type'),
374 _('Connection type'),
376 extratext
= _('Please select connection type, default choice should be best in most cases.')
382 Dynamically create next page for current settings.
384 self
.parent
.settings
.SetDriver(self
.names
[self
.GetType()])
385 next
= PhoneGammuDriverPage(self
.parent
)
389 class PhoneManufacturerPage(Wammu
.Wizard
.ChoicePage
):
391 Selects phone manufacturer.
393 def __init__(self
, parent
):
394 self
.names
, connections
, helps
= parent
.settings
.GetManufacturers()
396 Wammu
.Wizard
.ChoicePage
.__init
__(self
, parent
,
400 extratext
= _('Please select phone manufacturer or type. Try to be as specific as possible.'),
405 Dynamically create next page for current settings.
407 self
.parent
.settings
.SetManufacturer(self
.names
[self
.GetType()])
408 next
= PhoneDriverPage(self
.parent
)
412 class PhoneConnectionPage(Wammu
.Wizard
.ChoicePage
):
414 Selects phone connection type.
416 def __init__(self
, parent
, search
= True):
423 self
.names
.append('all')
424 connections
.append(_('Search all connections'))
425 helps
.append(_('Wizard will search for all possible connections. It might take quite long time to search all possible connection types.'))
427 self
.names
.append('usb')
428 connections
.append(_('USB cable'))
429 helps
.append(_('Many phones now come with USB cable, select this if you\'re using this connection type.'))
431 self
.names
.append('bluetooth')
432 connections
.append(_('Bluetooth'))
433 helps
.append(_('Bluetooth connection is wireless and does not require direct visibility. Phone needs to be properly paired with computer before proceeding.'))
435 self
.names
.append('irda')
436 connections
.append(_('IrDA'))
437 helps
.append(_('IrDA wireless connection requires direct visibility, please make sure this is fullfilled and computer can see phone.'))
439 self
.names
.append('serial')
440 connections
.append(_('Serial cable'))
441 helps
.append(_('This is not often used connection, but was very popular for older phones.'))
443 Wammu
.Wizard
.ChoicePage
.__init
__(self
, parent
,
444 _('Connection type'),
445 _('Connection type'),
447 extratext
= _('How is your phone connected?'),
451 self
.parent
.settings
.SetConnection(self
.names
[self
.GetType()])
452 return Wammu
.Wizard
.ChoicePage
.GetNext(self
)
454 class ConfigTypePage(Wammu
.Wizard
.ChoicePage
):
456 Allows user to select how to configure phone.
458 def __init__(self
, parent
, pg0
, pg1
, pg2
):
459 Wammu
.Wizard
.ChoicePage
.__init
__(self
, parent
,
460 _('Configuration style'),
461 _('Configuration style'),
463 _('Guided configuration'),
464 _('Automatically search for a phone'),
465 _('Manual configuration'),
469 _('You will be guided through configuration by phone connection type and vendor.'),
470 _('Wizard will attempt to search phone on usual ports.'),
471 _('You know what you are doing and know exact parameters you need for connecting to phone.'),
474 extratext
= _('How do you want to configure your phone connection?'),
476 self
.info
= wx
.StaticText(
479 _('If you have no idea how to configure your phone connection, you can look at Gammu Phone Database for other users experiences:'))
481 self
.sizer
.Add(self
.info
, 0, wx
.ALL
, 5)
482 self
.link
= wx
.lib
.hyperlink
.HyperLinkCtrl(
485 'http://%scihar.com/gammu/phonedb' % Wammu
.Utils
.GetWebsiteLang())
486 self
.sizer
.Add(self
.link
, 0, wx
.ALL
, 5)
488 class WelcomePage(Wammu
.Wizard
.SimplePage
):
490 First page of Wizard.
492 def __init__(self
, parent
):
493 Wammu
.Wizard
.SimplePage
.__init
__(self
, parent
, _('Welcome'),
494 _('This wizard will help you with configuring phone connection in Wammu.'),
497 _('Please make sure you have phone ready, powered on and one of connection methods is set up:'),
499 _('Cable is connected.'),
501 _('You have enabled IrDA and phone is in visible range.'),
503 _('You have paired Bluetooth with computer.'),
505 _('As soon as your phone is ready, you can continue.'),
508 class ConfigureWizard
:
509 def __init__(self
, parent
, position
= 0):
510 bmp
= wx
.Bitmap(Wammu
.Paths
.MiscPath('phonewizard'))
511 self
.wiz
= wx
.wizard
.Wizard(
514 _('Wammu Phone Configuration Wizard'),
516 self
.wiz
.settings
= Wammu
.SettingsStorage
.Settings()
517 self
.wiz
.settings
.SetPosition(position
)
519 self
.wiz
.Bind(wx
.wizard
.EVT_WIZARD_PAGE_CHANGING
, self
.OnPageChanging
)
520 self
.wiz
.Bind(wx
.wizard
.EVT_WIZARD_PAGE_CHANGED
, self
.OnPageChanged
)
521 self
.wiz
.Bind(wx
.wizard
.EVT_WIZARD_CANCEL
, self
.OnCancel
)
524 self
.pg_title
= WelcomePage(self
.wiz
)
526 self
.pg_search1
= PhoneConnectionPage(self
.wiz
)
527 self
.pg_search2
= PhoneSearchPage(self
.wiz
)
529 self
.pg_guide1
= PhoneConnectionPage(self
.wiz
, False)
530 self
.pg_guide2
= PhoneManufacturerPage(self
.wiz
)
532 self
.pg_manual1
= ManualPage(self
.wiz
)
534 self
.pg_type
= ConfigTypePage(
540 self
.pg_final
= FinalPage(self
.wiz
)
541 self
.pg_test
= TestPage(self
.wiz
)
542 self
.wiz
.pg_final
= self
.pg_final
543 self
.wiz
.pg_test
= self
.pg_test
546 self
.pg_title
.SetNext(self
.pg_type
)
547 self
.pg_type
.SetPrev(self
.pg_title
)
549 self
.pg_type
.SetNext(self
.pg_search1
) # overrided by it's GetNext
551 # Set previous page for all types
552 self
.pg_search1
.SetPrev(self
.pg_type
)
553 self
.pg_guide1
.SetPrev(self
.pg_type
)
554 self
.pg_manual1
.SetPrev(self
.pg_type
)
556 self
.pg_guide1
.SetNext(self
.pg_guide2
)
557 self
.pg_guide2
.SetPrev(self
.pg_guide1
)
558 # rest of guide is created dynamically
560 self
.pg_search1
.SetNext(self
.pg_search2
)
561 self
.pg_search2
.SetPrev(self
.pg_search1
)
562 # rest of search is created dynamically
565 self
.wiz
.FitToPage(self
.pg_title
)
567 def OnPageChanging(self
, evt
):
568 if evt
.GetPage().Blocked(evt
):
571 def OnPageChanged(self
, evt
):
572 evt
.GetPage().Activated(evt
)
574 def OnCancel(self
, evt
):
575 if not evt
.GetPage().Cancel(evt
):
579 return self
.wiz
.RunWizard(self
.pg_title
)
583 return self
.wiz
.settings
.GetSettings()
588 def RunConfigureWizard(parent
, position
= 0):
590 Executes wizard for configuring phone
592 return ConfigureWizard(parent
, position
).Execute()
594 class WizardApp(wx
.App
):
597 self
.SetAppName('Wammu Phone Configuration Wizard')
598 vendor
= StrConv(u
'Michal Čihař')
599 if vendor
.find('?') != -1:
600 vendor
= 'Michal Čihař'
601 self
.SetVendorName(vendor
)
603 wx
.InitAllImageHandlers()
605 # Return a success flag