1 __author__ = "Andrea Gavana <andrea.gavana@gmail.com>, <gavana@kpo.kz>"
2 __date__ = "01 Apr 2007, 13:15 GMT"
3 __version__ = "0.1"
4 __docformat__ = "epytext"
5
6
7 import os
8 import wx
9 import time
10
11 import wx.aui
12 import wx.lib.dialogs
13
14
15
16 import setuptools
17
18
19 import webbrowser
20
21
22 from ProjectTreeCtrl import ProjectTreeCtrl
23 from MessageWindow import MessageWindow
24 from AUINotebookPage import AUINotebookPage
25 from DataBase import DataBase
26 from Project import Project
27 from Process import Process
28 from Widgets import CustomCodeViewer, Py2ExeMissing
29 from Utilities import opj, odict
30 from Constants import _auiImageList, _pywild, _defaultCompilers
31
32
33 import AdvancedSplash as AS
34
35
36 ID_FirstPerspective = wx.ID_HIGHEST + 10001
37
38
39
40
41
43 """ Simple function that imports the available compilers (if any). """
44
45 compilers = odict()
46 for compiler in _defaultCompilers:
47 try:
48 module = __import__(compiler)
49 compilers[compiler] = module.__version__
50
51 except ImportError:
52
53 pass
54
55 return compilers
56
57
58 _compilers = ImportCompilers()
59
60
61
63
64 - def __init__(self, parent, id=-1, title="", pos=wx.DefaultPosition, size=wx.DefaultSize,
65 style=wx.DEFAULT_FRAME_STYLE):
66 """ Default wx.Frame class constructor. """
67
68 wx.Frame.__init__(self, parent, id, title, pos, size, style)
69
70
71 self._mgr = wx.aui.AuiManager()
72 self._mgr.SetManagedWindow(self)
73
74
75 self.installDir = os.getcwd()
76 self.autoSave = False
77 self.deleteBuild = True
78 self.process = None
79 self.exeTimer = wx.Timer(self)
80 self.timerCount = 0
81 self.processTimer = wx.Timer(self)
82
83 self.perspectives = []
84
85
86 self.CreateBar()
87
88 self.SetProperties()
89
90 self.CreateMenuBar()
91
92
93 self.BuildNBImageList()
94
95
96 dbName = self.CheckForDatabase()
97
98
99 self.projectTree = ProjectTreeCtrl(self)
100
101 self.mainPanel = wx.aui.AuiNotebook(self, -1, style=wx.aui.AUI_NB_DEFAULT_STYLE|
102 wx.aui.AUI_NB_WINDOWLIST_BUTTON)
103
104 self.messageWindow = MessageWindow(self)
105
106 self.dataBase = DataBase(self, dbName)
107
108
109
110 self._mgr.AddPane(self.projectTree, wx.aui.AuiPaneInfo().Left().
111 Caption("GUI2Exe Projects").MinSize(wx.Size(200, -1)).
112 FloatingSize(wx.Size(200, 300)).Layer(1).MaximizeButton())
113 self._mgr.AddPane(self.mainPanel, wx.aui.AuiPaneInfo().CenterPane())
114 self._mgr.AddPane(self.messageWindow, wx.aui.AuiPaneInfo().Bottom().
115 Caption("Messages And Actions").MinSize(wx.Size(200, 100)).
116 FloatingSize(wx.Size(500, 300)).BestSize(wx.Size(200, size[1]/6)).
117 MaximizeButton())
118
119
120 self.SetAllFlags()
121
122 self.BindEvents()
123
124
125 self.perspectives.append(self._mgr.SavePerspective())
126
127 self._mgr.Update()
128
129
130 self.ReadConfigurationFile()
131
132
133
134
135
136
138 """ Creates the GUI2Exe status bar. """
139
140
141
142 self.statusBar = self.CreateStatusBar(2, wx.ST_SIZEGRIP)
143 self.statusBar.SetStatusWidths([-1, -2])
144 self.FillStatusBar()
145
146
148 """ Handles all the information used to build the menu bar. """
149
150
151
152 return (("&File",
153 ("&New project...\tCtrl+N", "Add a new project to the project tree", "project", self.OnNewProject, ""),
154 ("Switch project &database...\tCtrl+D", "Load another GUI2Exe database file", "switch_db", self.OnSwitchDB, ""),
155 ("", "", "", "", ""),
156 ("&Save project\tCtrl+S", "Save the current project to database", "save_project", self.OnSaveProject, ""),
157 ("&Export setup file...\tCtrl+E", "Export the Setup.py file", "export_setup", self.OnExportSetup, ""),
158 ("", "", "", "", ""),
159 ("&Quit\tCtrl+Q", "Exit GUI2Exe", "exit", self.OnClose, "")),
160 ("&Options",
161 ("Use &AutoSave", "AutoSaves your work every minute", "", self.OnAutoSave, wx.ITEM_CHECK),
162 ('De&lete "build" directory', "Delete the build folder at every compilation", "", self.OnDeleteBuild, wx.ITEM_CHECK),
163 ("", "", "", "", ""),
164 ("&Test executable\tCtrl+R", "Test the compiled file (if it exists)", "runexe", self.OnTestExecutable, ""),
165 ("Add &custom code...\tCtrl+U", "Add custom code to the setup script", "custom_code", self.OnCustomCode, "")),
166 ("&View",
167 ("&Setup script\tCtrl+P", "View the auto-generated setup script", "view_setup", self.OnViewSetup, ""),
168 ("", "", "", "", ""),
169 ("&Missing modules\tCtrl+M", "What the compiler thinks are the missing modules", "missingmodules", self.OnViewMissing, ""),
170 ("&Binary dependencies\tCtrl+B", "What the compiler says are the binary dependencies", "binarydependencies", self.OnViewMissing, ""),
171 ("", "", "", "", ""),
172 ("Compiler s&witches\tCtrl+W", "Show compilers switches and common options", "compiler_switches", self.OnCompilerSwitches, ""),
173 ("&Tips and tricks\tCtrl+T", "Show compilation tips and tricks", "tips_and_tricks", self.OnTipsAndTricks, "")),
174 ("&Configuration",
175 ("Save &panes configuration...", "Save the current GUI panes configuration", "save_aui_config", self.OnSaveConfig, ""),
176 ("Restore original &GUI\tCtrl+G", "Restore the original GUI appearance", "restore_aui", self.OnRestorePerspective, "")),
177 ("&Help",
178 ("GUI2Exe &help\tF1", "Opens the GUI2Exe help", "help", self.OnHelp, ""),
179 ("GUI2Exe &API\tF2", "Opens the GUI2Exe API reference", "api_reference", self.OnAPI, ""),
180 ("", "", "", "", ""),
181 ("Check for &upgrade\tF5", "Check for a GUI2Exe upgrade", "upgrade", self.OnCheckUpgrade, ""),
182 ("", "", "", "", ""),
183 ("&About GUI2Exe...", "About GUI2Exe and the Creator...", "about", self.OnAbout, "")))
184
185
187 """ Creates a menu based on input menu data. """
188
189 menu = wx.Menu()
190
191
192
193 for eachLabel, eachStatus, eachIcon, eachHandler, eachKind in menuData:
194
195 if not eachLabel:
196 menu.AppendSeparator()
197 continue
198
199
200
201 id = (eachLabel.find("Restore") >= 0 and [ID_FirstPerspective] or [-1])[0]
202
203 kind = (eachKind and [eachKind] or [wx.ITEM_NORMAL])[0]
204
205 menuItem = wx.MenuItem(menu, id, eachLabel, eachStatus, kind=kind)
206 if eachIcon:
207
208 menuItem.SetBitmap(self.CreateBitmap(eachIcon))
209
210 menu.AppendItem(menuItem)
211 if eachLabel.find('"build"') >= 0:
212
213 menuItem.Check(True)
214
215
216 self.Bind(wx.EVT_MENU, eachHandler, menuItem)
217
218 return menu
219
220
222 """ Creates the main frame menu bar. """
223
224 menuBar = wx.MenuBar()
225
226
227 for eachMenuData in self.MenuData():
228 menuLabel = eachMenuData[0]
229 menuItems = eachMenuData[1:]
230 menuBar.Append(self.CreateMenu(menuItems), menuLabel)
231
232
233 self.Bind(wx.EVT_MENU_RANGE, self.OnRestorePerspective, id=ID_FirstPerspective,
234 id2=ID_FirstPerspective+1000)
235
236
237 id = menuBar.FindMenu("Configuration")
238 self.configMenu = menuBar.GetMenu(id)
239
240
241 self.SetMenuBar(menuBar)
242
243
245 """ Builds a fake image list for wx.aui.AuiNotebook. """
246
247
248
249 self.nbImageList = []
250 for png in _auiImageList:
251 bmp = self.CreateBitmap(png)
252 self.nbImageList.append(bmp)
253
254
256 """ Sets the main frame properties (title, icon...). """
257
258 self.SetIcon(wx.Icon(opj(self.installDir + "/images/GUI2Exe.png"), wx.BITMAP_TYPE_PNG))
259 self.SetTitle("GUI2Exe v" + __version__)
260
261
263 """ Sets all the fancy flags for wxAUI and friends. """
264
265
266 self._mgr.SetFlags(self._mgr.GetFlags() ^ wx.aui.AUI_MGR_ALLOW_ACTIVE_PANE)
267 self._mgr.SetFlags(self._mgr.GetFlags() ^ wx.aui.AUI_MGR_TRANSPARENT_DRAG)
268
269
270 self._mgr.GetArtProvider().SetColor(wx.aui.AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR,
271 wx.Colour(128, 128, 128))
272 self._mgr.GetArtProvider().SetColor(wx.aui.AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR,
273 wx.WHITE)
274
275
276 self.mainPanel.SetUniformBitmapSize((16, 16))
277
278
280 """ Checks if a database exists. If it doesn't, creates one anew. """
281
282
283
284 standardPath = wx.StandardPaths.Get()
285 configDir = opj(standardPath.GetUserConfigDir() + "/.GUI2Exe")
286 configDb = opj(configDir + "/GUI2Exe_Database.db")
287
288 if not os.path.isfile(configDb):
289
290 if not os.path.isdir(configDir):
291
292 os.mkdir(configDir)
293
294 return configDb
295
296
298 """ Binds all the events related to GUI2Exe. """
299
300 self.Bind(wx.EVT_CLOSE, self.OnClose)
301
302 self.Bind(wx.EVT_QUERY_END_SESSION, self.OnClose)
303
304 self.Bind(wx.EVT_END_PROCESS, self.OnProcessEnded)
305 self.Bind(wx.EVT_TIMER, self.OnExeTimer, self.exeTimer)
306
307
308
309 self.Bind(wx.EVT_TIMER, self.OnProcessTimer, self.processTimer)
310
311
312
313 self.mainPanel.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnPageClosing)
314 self.mainPanel.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGING, self.OnPageChanging)
315
316
318 """ Reads the default configuration file (default project initialization). """
319
320
321 self.defaultConfig = {"py2exe": {}}
322 fid = open(opj(self.installDir + "/defaultConfig.txt"), "rt")
323
324 section = 0
325
326 while 1:
327
328 tline = fid.readline()
329
330 if not tline:
331 fid.close()
332 break
333
334 if tline.find("%%") >= 0:
335
336 current = self.defaultConfig[tline.replace("%%", "").strip()]
337 continue
338
339
340
341 if tline.find("--") >= 0:
342 section += 1
343 continue
344
345 config, projectSwitches = tline.strip().split(":")
346
347 if section:
348
349 projectSwitches = eval(projectSwitches)
350 else:
351
352 projectSwitches = projectSwitches.strip()
353
354 current[config] = projectSwitches
355
356
357
358
359
360
362 """ A new project is being created. """
363
364
365 self.projectTree.NewProject()
366 event.Skip()
367
368
370 """ Switch to another project database. """
371
372
373 event.Skip()
374
375
377 """ Saves the current project. """
378
379 project = self.GetCurrentProject()
380 if not project:
381
382 return
383
384
385 self.SaveProject(project)
386
387
389 """ Exports the Setup.py file. """
390
391 page = self.GetCurrentPage()
392 if not page:
393
394 return
395
396 outputs = page.PrepareForCompile()
397 if not outputs:
398
399
400 return
401
402
403
404 setupScript, buildDir = outputs
405
406
407 dlg = wx.FileDialog(self, message="Save file as ...", defaultDir=buildDir,
408 defaultFile="Setup.py", wildcard=_pywild,
409 style=wx.FD_SAVE|wx.FD_OVERWRITE_PROMPT)
410
411
412
413 if dlg.ShowModal() == wx.ID_OK:
414 path = dlg.GetPath()
415
416
417 fp = file(path, 'w')
418 fp.write(setupScript)
419 fp.close()
420 self.SendMessage("Message", "File %s successfully saved"%path)
421
422
423
424 dlg.Destroy()
425 event.Skip()
426
427
429 """ Handles the wx.EVT_CLOSE event for the main frame. """
430
431 if self.exeTimer.IsRunning():
432
433 self.exeTimer.Stop()
434
435 if self.process is not None:
436
437 self.process.Kill()
438 self.processTimer.Stop()
439
440
441
442 for pageNumber in xrange(self.mainPanel.GetPageCount()-1, -1, -1):
443 if not self.HandlePageClosing(pageNumber, event):
444
445 return
446
447
448 self._mgr.UnInit()
449
450 self.Destroy()
451
452
453 - def OnPageClosing(self, event):
454 """ Handles the wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE event. """
455
456
457 selection = event.GetSelection()
458
459 self.HandlePageClosing(selection, event)
460
461
462 - def OnPageChanging(self, event):
463 """ Handles the wx.aui.EVT_AUINOTEBOOK_PAGE_CHANGING event. """
464
465
466 newBook = self.mainPanel.GetPage(event.GetSelection())
467 self.projectTree.HighlightItem(newBook.GetTreeItem(), True)
468
469 if event.GetOldSelection() >= 0:
470
471 oldBook = self.mainPanel.GetPage(event.GetOldSelection())
472 self.projectTree.HighlightItem(oldBook.GetTreeItem(), False)
473
474 event.Skip()
475
476
478 """ Enables/Disables the AutoSave feature. """
479
480
481 self.autoSave = event.IsChecked()
482 event.Skip()
483
484
486 """ Enables/Disables the automatic removal of the "build" folder. """
487
488
489 self.deleteBuild = event.IsChecked()
490 event.Skip()
491
492
494 """ Test the compiled executable. """
495
496 project = self.GetCurrentProject()
497 if not project:
498
499 return
500
501 if not project.HasBeenCompiled():
502
503 msg = "This project has not been compiled yet."
504 self.RunError("Error", msg)
505 return
506
507
508 self.SuccessfulCompilation(project, False)
509
510
512 """ Allows the user to add custom code to the Setup.py file. """
513
514 project = self.GetCurrentProject()
515 if not project:
516
517 return
518
519 currentPage = self.mainPanel.GetSelection()
520
521 customCode = project.GetCustomCode()
522
523
524 frame = CustomCodeViewer(self, readOnly=False, text=customCode, project=project,
525 page=currentPage)
526 event.Skip()
527
528
530 """ Allows the user to see the Setup.py file. """
531
532 wx.BeginBusyCursor()
533
534 self.RunCompile(view=True, run=False)
535 wx.EndBusyCursor()
536 event.Skip()
537
538
540 """ Shows the missing modules and dlls. """
541
542 project = self.GetCurrentProject()
543 if not project:
544
545 return
546
547 if not project.HasBeenCompiled():
548
549 msg = "This project has not been compiled yet."
550 self.RunError("Error", msg)
551 return
552
553 wx.BeginBusyCursor()
554
555
556 label = self.GetMenuBar().GetLabel(event.GetId())
557 dll = (label.find("Binary") >= 0 and [True] or [False])[0]
558
559 frame = Py2ExeMissing(self, project, dll)
560
561 wx.EndBusyCursor()
562
563
565 """ Shows the different compiler switches/options. """
566
567 webbrowser.open_new(opj(self.installDir + "/docs/switches.html"))
568 event.Skip()
569
570
572 """ Shows the compilation tips and tricks. """
573
574 webbrowser.open_new("http://www.py2exe.org/index.cgi/WorkingWithVariousPackagesAndModules")
575 event.Skip()
576
577
579 """ Saves the current GUI configuration, in terms of panes positions. """
580
581
582 dlg = wx.TextEntryDialog(self, "Enter A Name For The New Configuration:",
583 "Saving Panels Configuration")
584 dlg.SetValue(("Perspective %d")%(len(self.perspectives)))
585
586 if dlg.ShowModal() != wx.ID_OK:
587
588 return
589
590 value = dlg.GetValue()
591 dlg.Destroy()
592
593 if not value.strip():
594
595 self.RunError("Error", "Invalid perspective name!")
596 return
597
598 if len(self.perspectives) == 1:
599
600 self.configMenu.AppendSeparator()
601
602
603 item = wx.MenuItem(self.configMenu, ID_FirstPerspective + len(self.perspectives), value,
604 "Restore GUI configuration: %s"%value)
605 item.SetBitmap(self.CreateBitmap("aui_config"))
606 self.configMenu.AppendItem(item)
607
608
609 self.perspectives.append(self._mgr.SavePerspective())
610
611 event.Skip()
612
613
615 """ Restore the selected GUI perspective. """
616
617 self._mgr.LoadPerspective(self.perspectives[event.GetId() - ID_FirstPerspective])
618 self._mgr.Update()
619
620
622 """ Shows the GUI2Exe help file. """
623
624
625 event.Skip()
626
627
629 """ Shows the GUI2Exe API help file. """
630
631
632 event.Skip()
633
634
636 """ Checks for a possible upgrade of GUI2Exe. """
637
638
639 event.Skip()
640
641
643 """ Shows the about dialog for GUI2Exe. """
644
645 msg = "This is the about dialog of GUI2Exe.\n\n" + \
646 "Version %s"%__version__ + "\n"+ \
647 "Author: Andrea Gavana @ 01 Apr 2007\n\n" + \
648 "Please report any bug/request of improvements\n" + \
649 "to me at the following addresses:\n\n" + \
650 "andrea.gavana@gmail.com\ngavana@kpo.kz\n\n" + \
651 "Thanks to Robin Dunn and the wxPython mailing list\n" + \
652 "for the ideas and useful suggestions."
653
654 self.RunError("Message", msg)
655 event.Skip()
656
657
659 """ Handles the wx.EVT_TIMER event for the main frame. """
660
661
662
663 if self.process is not None:
664
665 self.process.HandleProcessMessages()
666
667 event.Skip()
668
669
671 """ Handles the wx.EVT_END_PROCESS for the main frame. """
672
673
674 self.processTimer.Stop()
675
676
677 self.process.HandleProcessMessages(True)
678
679 wx.CallAfter(self.process.Destroy)
680
681 self.messageWindow.EnableButtons(True)
682
683 event.Skip()
684
685
687 """ Handles the wx.EVT_TIMER event for the main frame. """
688
689
690 self.timerCount += 1
691 logFile = self.currentExe + ".log"
692 if os.path.isfile(logFile):
693
694 self.exeTimer.Stop()
695
696 self.ExamineLogFile(logFile)
697
698 if self.timerCount > 200:
699
700
701 self.exeTimer.Stop()
702 self.currentExe = None
703 self.timerCount = 0
704
705 event.Skip()
706
707
708
709
710
711
712 - def HandlePageClosing(self, selection, event):
713
714
715 unSaved = self.mainPanel.GetPageBitmap(selection) == self.nbImageList[1]
716
717
718 page = self.mainPanel.GetPage(selection)
719 project = page.GetProject()
720 treeItem = page.GetTreeItem()
721
722 isCloseEvent = isinstance(event, wx.CloseEvent)
723
724 if not unSaved:
725
726 self.projectTree.SetItemEditing(treeItem, False)
727 if not isCloseEvent:
728 event.Skip()
729 return True
730
731
732
733 msg = "Warning: the selected page contains unsaved data.\n\nDo you wish to save this project?"
734 answer = self.RunError("Question", msg)
735
736 if answer == wx.ID_CANCEL:
737
738 event.Veto()
739 return False
740 elif answer == wx.ID_YES:
741
742 self.dataBase.SaveProject(project)
743 if not isCloseEvent:
744
745 event.Skip()
746 else:
747
748 projectExists = self.dataBase.IsProjectExisting(project)
749 if not isCloseEvent:
750 event.Skip()
751
752 if not projectExists:
753
754 self.projectTree.DeleteProject([treeItem])
755 else:
756
757 self.projectTree.SetItemEditing(treeItem, False)
758
759 return True
760
761
763 """ Saves the current project. """
764
765
766 self.dataBase.SaveProject(project)
767
768 self.UpdatePageBitmap(project.GetName(), 0, self.mainPanel.GetSelection())
769
770
771 - def UpdatePageBitmap(self, pageName, pageIcon, selection=None):
772 """
773 Updates the wx.aui.AuiNotebook page image and text, to reflect the
774 current project state (saved/unsaved).
775 """
776
777 if selection is None:
778
779 selection = self.mainPanel.GetSelection()
780
781 if self.mainPanel.GetPageBitmap(selection) == self.nbImageList[pageIcon]:
782
783 return
784
785
786 self.mainPanel.SetPageBitmap(selection, self.nbImageList[pageIcon])
787 self.mainPanel.SetPageText(selection, pageName)
788
789
790 - def RunError(self, kind, msg, sendMessage=False):
791 """
792 An utility method that shows a message dialog with different functionalities
793 depending on the input.
794 """
795
796 if sendMessage:
797
798 self.SendMessage(kind, msg.strip("."))
799
800 if kind == "Message":
801 style = wx.OK | wx.ICON_INFORMATION
802 elif kind == "Warning":
803 style = wx.OK | wx.ICON_EXCLAMATION
804 elif kind == "Question":
805 style = wx.YES_NO | wx.CANCEL | wx.ICON_QUESTION
806 else:
807 style = wx.OK | wx.ICON_ERROR
808
809
810 dlg = wx.MessageDialog(None, msg, "GUI2Exe %s"%kind, style|wx.STAY_ON_TOP)
811 answer = dlg.ShowModal()
812 dlg.Destroy()
813
814 if kind == "Question":
815
816 return answer
817
818
820 """ Adds a new project to the current center pane. """
821
822
823 busy = wx.BusyInfo("Creating new project...")
824 self.Freeze()
825
826
827 project = Project(self.defaultConfig, projectName)
828
829
830 self.Project(project, treeItem, True)
831
832
833 self.SendMessage("Message", 'New project "%s" added'%projectName)
834
835
836 self.Thaw()
837 del busy
838
839
841 """ Loads a project in the center pane. """
842
843
844 page = self.IsAlreadyOpened(treeItem)
845 if page is not None:
846
847 self.mainPanel.SetSelection(page)
848 return
849
850
851 project = self.dataBase.LoadProject(projectName)
852
853 self.Project(project, treeItem, False)
854
855 self.SendMessage("Message", 'Project "%s" successfully loaded'%projectName)
856
857
859 """ The user has renamed the project in the project tree control. """
860
861
862 project = self.dataBase.RenameProject(oldName, newName)
863
864 page = self.WalkAUIPages(treeItem)
865 if page is None:
866
867 return
868
869
870 self.mainPanel.SetPageText(page, newName)
871 book = self.mainPanel.GetPage(page)
872 if project is None:
873
874 project = book.GetProject()
875 project.SetName(newName)
876
877 book.SetProject(project)
878
879 book.GetPage(0).UpdateLabel(project.GetName(), project.GetCreationDate())
880
881
882 - def Project(self, project, treeItem, isNew):
883 """ Auxiliary method used to actually add a page to the center pane. """
884
885
886 projectName = project.GetName()
887
888 page = AUINotebookPage(self.mainPanel, project, _compilers)
889
890 pageName = (isNew and [projectName+"*"] or [projectName])[0]
891 bmp = (isNew and [1] or [0])[0]
892
893
894 page.SetProject(project)
895 page.SetTreeItem(treeItem)
896
897
898 self.mainPanel.AddPage(page, pageName, True, bitmap=self.nbImageList[bmp])
899
900
901 - def WalkAUIPages(self, treeItem):
902 """ Walks over all the opened page in the center pane. """
903
904
905 for indx in xrange(self.mainPanel.GetPageCount()):
906 page = self.mainPanel.GetPage(indx)
907 if page.GetTreeItem() == treeItem:
908
909 return indx
910
911
912 return None
913
914
916 """ Looks if a page is already opened. """
917
918 return self.WalkAUIPages(treeItem)
919
920
921 - def CloseAssociatedPage(self, treeItem):
922 """
923 A method used to close a wx.aui.AuiNotebook page when an item in the
924 project tree is deleted.
925 """
926
927 page = self.WalkAUIPages(treeItem)
928 if page is not None:
929 self.mainPanel.DeletePage(page)
930
931
932 - def ReassignPageItem(self, oldItem, newItem):
933 """ Reassigns an item to an opened page after a drag and drop operation. """
934
935 page = self.WalkAUIPages(oldItem)
936 if page is not None:
937
938 page = self.mainPanel.GetPage(page)
939 page.SetTreeItem(newItem)
940
941
943 """ Fills the statusbar fields with different information. """
944
945
946 wxPythonVersion = wx.version()
947 statusText = "wxPython %s"%wxPythonVersion
948
949 for compiler, version in _compilers.items():
950
951 statusText += ", %s %s"%(compiler, version)
952
953
954 self.statusBar.SetStatusText(statusText, 1)
955 self.statusBar.SetStatusText("Welcome to GUI2Exe", 0)
956
957
959 """ Utility function to create bitmap passing a filename. """
960
961 bmp = wx.Bitmap(opj(self.installDir + "/images/%s.png"%fileName), wx.BITMAP_TYPE_PNG)
962 return bmp
963
964
965 - def GetCurrentPage(self):
966 """ Returns the current LabelBook page. """
967
968 book = self.GetCurrentBook()
969 if not book:
970
971 return
972
973 return book.GetPage(book.GetSelection())
974
975
977 """ Returns the current wx.aui.AuiNotebook page (a LabelBook). """
978
979 if self.mainPanel.GetPageCount() == 0:
980
981 msg = "No project has been loaded"
982 self.RunError("Error", msg +".", True)
983 return None
984
985
986 selection = self.mainPanel.GetSelection()
987 return self.mainPanel.GetPage(selection)
988
989
991 """ Returns the current project associated to a LabelBook. """
992
993 book = self.GetCurrentBook()
994 if not book:
995
996 return
997
998 return book.GetProject()
999
1000
1002 """
1003 Auxiliary method. Depending on the input, it does different things:
1004 - view=True ==> Get the Setup.py script and displays it (run is discarded);
1005 - run=False ==> Start a dry-run (a compilation that does nothing);
1006 - run=True ==> Start the real compilation process.
1007 """
1008
1009 page = self.GetCurrentPage()
1010 if not page:
1011
1012 return
1013
1014 outputs = page.PrepareForCompile()
1015 if not outputs:
1016
1017
1018 return
1019
1020 setupScript, buildDir = outputs
1021
1022 if view:
1023 frame = CustomCodeViewer(self, readOnly=True, text=setupScript)
1024 return
1025
1026
1027 self.messageWindow.EnableButtons(False)
1028
1029
1030 compiler = page.GetName()
1031 project = self.GetCurrentProject()
1032 currentPage = self.mainPanel.GetSelection()
1033
1034
1035
1036 self.process = Process(self, buildDir, setupScript, run, compiler,
1037 project, currentPage)
1038
1039
1040 self.processTimer.Start(500)
1041
1042 self.process.Start()
1043
1044
1046 """ Kills (or tries to) the compilation process. """
1047
1048 if self.process:
1049
1050 self.processTimer.Stop()
1051
1052
1053 self.process.Kill()
1054
1055 self.SendMessage("Warning", "Compilation killed by user")
1056
1057 self.messageWindow.EnableButtons(True)
1058
1059
1061 """
1062 Assumes that the compilation process was successful and tries to test
1063 the new exe file.
1064 """
1065
1066 if ask:
1067
1068 msg = "The compiler has successfully built your executable.\n" \
1069 "Do you wish to test your application?"
1070 answer = self.RunError("Question", msg)
1071 if answer != wx.ID_YES:
1072 return
1073
1074
1075 exeName = project.GetExecutableName("py2exe")
1076 if not os.path.isfile(exeName):
1077
1078 msg = "This project has never been compiled or its executable has been deleted."
1079 self.RunError("Error", msg)
1080 return
1081
1082
1083 msg = "Starting compiled executable..."
1084 busy = wx.BusyInfo(msg)
1085 self.SendMessage("Message", msg)
1086
1087 logFile = exeName + ".log"
1088
1089 if os.path.isfile(logFile):
1090 try:
1091 os.remove(logFile)
1092 except:
1093 pass
1094
1095 self.currentExe = exeName
1096
1097 self.exeTimer.Start(100)
1098 os.spawnl(os.P_NOWAIT, exeName)
1099
1100 del busy
1101 wx.SafeYield()
1102
1103
1105 """ Examine a log file, created by an executable that crashed fpr some reason. """
1106
1107
1108 self.currentExe = None
1109 self.timerCount = 0
1110
1111
1112 self.SendMessage("Error", "Executable terminated with errors or warnings")
1113
1114
1115 msg = "It appears that the executable generated errors in file:\n\n%s" % logFile
1116 msg += "\n\nDo you want to examine the tracebacks?"
1117 answer = self.RunError("Question", msg)
1118 if answer != wx.ID_YES:
1119 return
1120
1121 wx.BeginBusyCursor()
1122
1123
1124 fid = open(logFile, "rt")
1125 msg = fid.read()
1126 fid.close()
1127
1128 dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg, "Tracebacks in log file")
1129 wx.EndBusyCursor()
1130 dlg.ShowModal()
1131 dlg.Destroy()
1132
1133
1135 """ Sends a message to the log window at the bottom. """
1136
1137 self.messageWindow.SendMessage(kind, message)
1138
1139
1141 """ Return the current GUI2Exe version. """
1142
1143 return __version__
1144
1145
1147
1149 """ A fancy splash screen :-D """
1150
1151 bmp = wx.Bitmap("images/gui2exe_splash.png", wx.BITMAP_TYPE_PNG)
1152 AS.AdvancedSplash.__init__(self, None, bitmap=bmp, timeout=5000,
1153 extrastyle=AS.AS_TIMEOUT|AS.AS_CENTER_ON_SCREEN)
1154
1155 self.Bind(wx.EVT_CLOSE, self.OnClose)
1156 self.fc = wx.FutureCall(2000, self.ShowMain)
1157 self.app = app
1158
1159
1161 """ Handles the wx.EVT_CLOSE event for GUI2ExeSplashScreen. """
1162
1163
1164
1165 evt.Skip()
1166 self.Hide()
1167
1168
1169
1170 if self.fc.IsRunning():
1171
1172 self.fc.Stop()
1173 self.ShowMain()
1174
1175
1176 - def ShowMain(self):
1177 """ Shows the main application (GUI2Exe). """
1178
1179
1180 size = wx.GetDisplaySize()
1181
1182 xvideo, yvideo = 5*size.x/6, 5*size.y/6
1183 frame = GUI2Exe(None, -1, "", size=(xvideo, yvideo))
1184
1185 self.app.SetTopWindow(frame)
1186 frame.CenterOnScreen()
1187 frame.Show()
1188
1189 if self.fc.IsRunning():
1190 self.Raise()
1191
1192
1194
1196
1197 splash = GUI2ExeSplashScreen(self)
1198 splash.Show()
1199
1200 self.SetAppName("GUI2Exe")
1201
1202 return True
1203
1204
1205 if __name__ == "__main__":
1206 app = GUI2ExeApp(0)
1207 app.MainLoop()
1208