chiark / gitweb /
RC1
[cura.git] / Cura / gui / app.py
1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
2
3 import sys
4 import os
5 import platform
6 import shutil
7 import glob
8 import warnings
9
10 try:
11         #Only try to import the _core to save import time
12         import wx._core
13 except ImportError:
14         import wx
15
16
17 class CuraApp(wx.App):
18         def __init__(self, files):
19                 if platform.system() == "Windows" and not 'PYCHARM_HOSTED' in os.environ:
20                         from Cura.util import profile
21                         super(CuraApp, self).__init__(redirect=True, filename=os.path.join(profile.getBasePath(), 'output_log.txt'))
22                 else:
23                         super(CuraApp, self).__init__(redirect=False)
24
25                 self.mainWindow = None
26                 self.splash = None
27                 self.loadFiles = files
28
29                 self.Bind(wx.EVT_ACTIVATE_APP, self.OnActivate)
30
31                 if sys.platform.startswith('win'):
32                         #Check for an already running instance, if another instance is running load files in there
33                         from Cura.util import version
34                         from ctypes import windll
35                         import ctypes
36                         import socket
37                         import threading
38
39                         portNr = 0xCA00 + sum(map(ord, version.getVersion(False)))
40                         if len(files) > 0:
41                                 try:
42                                         other_hwnd = windll.user32.FindWindowA(None, ctypes.c_char_p('Cura - ' + version.getVersion()))
43                                         if other_hwnd != 0:
44                                                 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
45                                                 sock.sendto('\0'.join(files), ("127.0.0.1", portNr))
46
47                                                 windll.user32.SetForegroundWindow(other_hwnd)
48                                                 return
49                                 except:
50                                         pass
51
52                         socketListener = threading.Thread(target=self.Win32SocketListener, args=(portNr,))
53                         socketListener.daemon = True
54                         socketListener.start()
55
56                 if sys.platform.startswith('darwin'):
57                         #Do not show a splashscreen on OSX, as by Apple guidelines
58                         self.afterSplashCallback()
59                 else:
60                         from Cura.gui import splashScreen
61                         self.splash = splashScreen.splashScreen(self.afterSplashCallback)
62
63         def MacOpenFile(self, path):
64                 try:
65                         self.mainWindow.OnDropFiles([path])
66                 except Exception as e:
67                         warnings.warn("File at {p} cannot be read: {e}".format(p=path, e=str(e)))
68
69         def MacReopenApp(self, event):
70                 self.GetTopWindow().Raise()
71
72         def MacHideApp(self, event):
73                 self.GetTopWindow().Show(False)
74
75         def MacNewFile(self):
76                 pass
77
78         def MacPrintFile(self, file_path):
79                 pass
80
81         def OnActivate(self, e):
82                 if e.GetActive():
83                         self.GetTopWindow().Raise()
84                 e.Skip()
85
86         def Win32SocketListener(self, port):
87                 import socket
88                 try:
89                         sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
90                         sock.bind(("127.0.0.1", port))
91                         while True:
92                                 data, addr = sock.recvfrom(2048)
93                                 try:
94                                         wx.CallAfter(self.mainWindow.OnDropFiles, data.split('\0'))
95                                 except Exception as e:
96                                         warnings.warn("File at {p} cannot be read: {e}".format(p=data, e=str(e)))
97                 except:
98                         pass
99
100         def afterSplashCallback(self):
101                 #These imports take most of the time and thus should be done after showing the splashscreen
102                 import webbrowser
103                 from Cura.gui import mainWindow
104                 from Cura.gui import configWizard
105                 from Cura.gui import newVersionDialog
106                 from Cura.util import profile
107                 from Cura.util import resources
108                 from Cura.util import version
109
110                 resources.setupLocalization(profile.getPreference('language'))  # it's important to set up localization at very beginning to install _
111
112                 #If we do not have preferences yet, try to load it from a previous Cura install
113                 if profile.getMachineSetting('machine_type') == 'unknown':
114                         try:
115                                 otherCuraInstalls = profile.getAlternativeBasePaths()
116                                 for path in otherCuraInstalls[::-1]:
117                                         try:
118                                                 print 'Loading old settings from %s' % (path)
119                                                 profile.loadPreferences(os.path.join(path, 'preferences.ini'))
120                                                 profile.loadProfile(os.path.join(path, 'current_profile.ini'))
121                                                 break
122                                         except:
123                                                 import traceback
124                                                 print traceback.print_exc()
125                         except:
126                                 import traceback
127                                 print traceback.print_exc()
128
129                 #If we haven't run it before, run the configuration wizard.
130                 if profile.getMachineSetting('machine_type') == 'unknown':
131                         #Check if we need to copy our examples
132                         exampleFile = os.path.normpath(os.path.join(resources.resourceBasePath, 'example', 'UltimakerRobot_support.stl'))
133
134                         self.loadFiles = [exampleFile]
135                         if self.splash is not None:
136                                 self.splash.Show(False)
137                         configWizard.ConfigWizard()
138
139                 if profile.getPreference('check_for_updates') == 'True':
140                         newVersion = version.checkForNewerVersion()
141                         if newVersion is not None:
142                                 if self.splash is not None:
143                                         self.splash.Show(False)
144                                 if wx.MessageBox(_("A new version of Cura is available, would you like to download?"), _("New version available"), wx.YES_NO | wx.ICON_INFORMATION) == wx.YES:
145                                         webbrowser.open(newVersion)
146                                         return
147                 if profile.getMachineSetting('machine_name') == '':
148                         return
149                 self.mainWindow = mainWindow.mainWindow()
150                 if self.splash is not None:
151                         self.splash.Show(False)
152                 self.SetTopWindow(self.mainWindow)
153                 self.mainWindow.Show()
154                 self.mainWindow.OnDropFiles(self.loadFiles)
155                 if profile.getPreference('last_run_version') != version.getVersion(False):
156                         profile.putPreference('last_run_version', version.getVersion(False))
157                         newVersionDialog.newVersionDialog().Show()
158
159                 setFullScreenCapable(self.mainWindow)
160
161                 if sys.platform.startswith('darwin'):
162                         wx.CallAfter(self.StupidMacOSWorkaround)
163
164         def StupidMacOSWorkaround(self):
165                 """
166                 On MacOS for some magical reason opening new frames does not work until you opened a new modal dialog and closed it.
167                 If we do this from software, then, as if by magic, the bug which prevents opening extra frames is gone.
168                 """
169                 dlg = wx.Dialog(None)
170                 wx.PostEvent(dlg, wx.CommandEvent(wx.EVT_CLOSE.typeId))
171                 dlg.ShowModal()
172                 dlg.Destroy()
173
174 if platform.system() == "Darwin": #Mac magic. Dragons live here. THis sets full screen options.
175         try:
176                 import ctypes, objc
177                 _objc = ctypes.PyDLL(objc._objc.__file__)
178
179                 # PyObject *PyObjCObject_New(id objc_object, int flags, int retain)
180                 _objc.PyObjCObject_New.restype = ctypes.py_object
181                 _objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
182
183                 def setFullScreenCapable(frame):
184                         frameobj = _objc.PyObjCObject_New(frame.GetHandle(), 0, 1)
185
186                         NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7
187                         window = frameobj.window()
188                         newBehavior = window.collectionBehavior() | NSWindowCollectionBehaviorFullScreenPrimary
189                         window.setCollectionBehavior_(newBehavior)
190         except:
191                 def setFullScreenCapable(frame):
192                         pass
193
194 else:
195         def setFullScreenCapable(frame):
196                 pass