1 __copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License"
12 #Only try to import the _core to save import time
18 class CuraApp(wx.App):
19 def __init__(self, files):
20 if platform.system() == "Windows" and not 'PYCHARM_HOSTED' in os.environ:
21 from Cura.util import profile
22 super(CuraApp, self).__init__(redirect=True, filename=os.path.join(profile.getBasePath(), 'output_log.txt'))
24 super(CuraApp, self).__init__(redirect=False)
26 self.mainWindow = None
28 self.loadFiles = files
30 if platform.system() == "Darwin":
31 self.Bind(wx.EVT_ACTIVATE_APP, self.OnActivate)
33 if sys.platform.startswith('win'):
34 #Check for an already running instance, if another instance is running load files in there
35 from Cura.util import version
36 from ctypes import windll
41 portNr = 0xCA00 + sum(map(ord, version.getVersion(False)))
44 other_hwnd = windll.user32.FindWindowA(None, ctypes.c_char_p('Cura - ' + version.getVersion()))
46 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
47 sock.sendto('\0'.join(files), ("127.0.0.1", portNr))
49 windll.user32.SetForegroundWindow(other_hwnd)
54 socketListener = threading.Thread(target=self.Win32SocketListener, args=(portNr,))
55 socketListener.daemon = True
56 socketListener.start()
58 if sys.platform.startswith('darwin'):
59 #Do not show a splashscreen on OSX, as by Apple guidelines
60 self.afterSplashCallback()
62 from Cura.gui import splashScreen
63 self.splash = splashScreen.splashScreen(self.afterSplashCallback)
65 def MacOpenFile(self, path):
67 self.mainWindow.OnDropFiles([path])
68 except Exception as e:
69 warnings.warn("File at {p} cannot be read: {e}".format(p=path, e=str(e)))
71 def MacReopenApp(self, event):
72 self.GetTopWindow().Raise()
74 def MacHideApp(self, event):
75 self.GetTopWindow().Show(False)
80 def MacPrintFile(self, file_path):
83 def OnActivate(self, e):
85 self.GetTopWindow().Raise()
88 def Win32SocketListener(self, port):
91 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
92 sock.bind(("127.0.0.1", port))
94 data, addr = sock.recvfrom(2048)
96 wx.CallAfter(self.mainWindow.OnDropFiles, data.split('\0'))
97 except Exception as e:
98 warnings.warn("File at {p} cannot be read: {e}".format(p=data, e=str(e)))
102 def destroySplashScreen(self):
103 if self.splash is not None:
104 self.splash.Show(False)
105 self.splash.Destroy()
108 def afterSplashCallback(self):
109 #These imports take most of the time and thus should be done after showing the splashscreen
111 from Cura.gui import mainWindow
112 from Cura.gui import configWizard
113 from Cura.gui import newVersionDialog
114 from Cura.util import profile
115 from Cura.util import resources
116 from Cura.util import version
118 resources.setupLocalization(profile.getPreference('language')) # it's important to set up localization at very beginning to install _
121 from distutils.version import LooseVersion
123 if LooseVersion(wx.__version__) < LooseVersion('3.0'):
124 wx.MessageBox(_("This version of Cura requires WxPython version 3.0 or newer.\nYour current WxPython version is %s.") % wx.__version__,
125 _("WxPython version is too old"), wx.OK | wx.ICON_ERROR)
128 # distutils not found.. it can happen!
129 # Only check the first 3 characters of the version string instead
130 if float(wx.__version__[0:3]) < 3.0:
131 wx.MessageBox(_("This version of Cura requires WxPython version 3.0 or newer.\nYour current WxPython version is %s.") % wx.__version__,
132 _("WxPython version is too old"), wx.OK | wx.ICON_ERROR)
135 #If we do not have preferences yet, try to load it from a previous Cura install
136 if profile.getMachineSetting('machine_type') == 'unknown':
138 otherCuraInstalls = profile.getAlternativeBasePaths()
139 for path in otherCuraInstalls[::-1]:
141 print 'Loading old settings from %s' % (path)
142 profile.loadPreferences(os.path.join(path, 'preferences.ini'))
143 profile.loadProfile(os.path.join(path, 'current_profile.ini'))
147 print traceback.print_exc()
150 print traceback.print_exc()
152 #If we haven't run it before, run the configuration wizard.
153 if profile.getMachineSetting('machine_type') == 'unknown':
154 #Check if we need to copy our examples
155 exampleFile = os.path.normpath(os.path.join(resources.resourceBasePath, 'example', 'Rocktopus.stl'))
157 self.loadFiles = [exampleFile]
158 self.destroySplashScreen()
159 configWizard.ConfigWizard()
161 if profile.getPreference('check_for_updates') == 'True':
162 newVersion = version.checkForNewerVersion()
163 if newVersion is not None:
164 self.destroySplashScreen()
165 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:
166 webbrowser.open(newVersion)
168 if profile.getMachineSetting('machine_name') == '':
170 if profile.getPreference('last_run_version') != version.getVersion(False):
171 profile.performVersionUpgrade()
173 # Must happen before the main window is created, in case there are changes
174 # that would affect it (such as machine name changes)
175 if version.isDevVersion():
176 profile.performVersionUpgrade()
178 self.mainWindow = mainWindow.mainWindow()
179 self.destroySplashScreen()
180 self.SetTopWindow(self.mainWindow)
181 self.mainWindow.Show()
182 self.mainWindow.OnDropFiles(self.loadFiles)
183 setFullScreenCapable(self.mainWindow)
185 if profile.getPreference('last_run_version') != version.getVersion(False):
186 profile.putPreference('last_run_version', version.getVersion(False))
187 newVersionDialog.newVersionDialog().Show()
189 # Must come after creating the main window
190 #if version.isDevVersion():
191 #import wx.lib.inspection
192 # Show the WX widget inspection tool
193 #wx.lib.inspection.InspectionTool().Show()
195 if sys.platform.startswith('darwin'):
196 wx.CallAfter(self.StupidMacOSWorkaround)
198 def StupidMacOSWorkaround(self):
199 subprocess.Popen(['osascript', '-e', '''\
200 tell application "System Events"
201 set procName to name of first process whose unix id is %s
203 tell application procName to activate
206 if platform.system() == "Darwin": #Mac magic. Dragons live here. THis sets full screen options.
209 _objc = ctypes.PyDLL(objc._objc.__file__)
211 # PyObject *PyObjCObject_New(id objc_object, int flags, int retain)
212 _objc.PyObjCObject_New.restype = ctypes.py_object
213 _objc.PyObjCObject_New.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int]
215 def setFullScreenCapable(frame):
216 frameobj = _objc.PyObjCObject_New(frame.GetHandle(), 0, 1)
218 NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7
219 window = frameobj.window()
220 newBehavior = window.collectionBehavior() | NSWindowCollectionBehaviorFullScreenPrimary
221 window.setCollectionBehavior_(newBehavior)
223 def setFullScreenCapable(frame):
227 def setFullScreenCapable(frame):