1 // -*- c-basic-offset: 4 -*-
2
3 /** @file hugin1/base_wx/platform.cpp
4 *
5 * @brief various platfrom specific wxWidgets functions
6 *
7 * @author Pablo d'Angelo <pablo.dangelo@web.de>
8 *
9 * $Id: huginApp.cpp 2510 2007-10-28 22:24:11Z dangelo $
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public
22 * License along with this software. If not, see
23 * <http://www.gnu.org/licenses/>.
24 *
25 */
26
27 #include "platform.h"
28
29 #include <hugin_utils/utils.h>
30 #include <vigra/imageinfo.hxx>
31
32 /** return vector of known extensions of raw files */
GetRawExtensions()33 std::vector<std::string> GetRawExtensions()
34 {
35 std::vector<std::string> rawExt{ "dng", "crw", "cr2","cr3","raw","erf","raf","mrw","nef","orf","rw2","pef","srw","arw" };
36 return rawExt;
37 };
38
39 /** build filter string "*.ext", adds also upper case version for UNIX paths when needed */
GetFilterExtensions(const wxString & ext)40 wxString GetFilterExtensions(const wxString& ext)
41 {
42 wxString extensionString("*.");
43 extensionString.Append(ext);
44 if (wxFileName::IsCaseSensitive())
45 {
46 extensionString.Append(";*.").Append(ext.Upper());
47 };
48 return extensionString;
49 };
50
GetVigraImageFilter()51 wxString GetVigraImageFilter()
52 {
53 wxString filterString;
54 const std::string extensions = vigra::impexListExtensions();
55 std::vector<std::string> exts = hugin_utils::SplitString(extensions, " ");
56 if (exts.empty())
57 {
58 // if something goes wrong, add some defaults
59 exts.push_back("tif");
60 exts.push_back("tiff");
61 exts.push_back("jpg");
62 exts.push_back("jpeg");
63 exts.push_back("png");
64 }
65 filterString.Append(_("All Image files")).Append("|");
66 for (auto& ext : exts)
67 {
68 filterString.Append(GetFilterExtensions(ext)).Append(";");
69 };
70 // remove last character == ";"
71 filterString.RemoveLast();
72 filterString.Append("|");
73 return filterString;
74 };
75
GetFileDialogImageFilters()76 wxString GetFileDialogImageFilters()
77 {
78 wxString filterString=GetVigraImageFilter();
79 filterString.Append(_("JPEG files (*.jpg,*.jpeg)")).Append("|").Append(GetFilterExtensions("jpg")).Append(";").Append(GetFilterExtensions("jpeg"));
80 filterString.Append("|").Append(_("TIFF files (*.tif,*.tiff)")).Append("|").Append(GetFilterExtensions("tif")).Append(";").Append(GetFilterExtensions("tiff"));
81 filterString.Append("|").Append(_("PNG files (*.png)")).Append("|").Append(GetFilterExtensions("png"));
82 filterString.Append("|").Append(_("HDR files (*.hdr)")).Append("|").Append(GetFilterExtensions("hdr"));
83 filterString.Append("|").Append(_("EXR files (*.exr)")).Append("|").Append(GetFilterExtensions("exr"));
84 filterString.Append("|").Append(_("All files (*)")).Append("|*");
85 return filterString;
86 }
87
GetFileDialogImageAndRawFilters()88 wxString GetFileDialogImageAndRawFilters()
89 {
90 wxString filterString = GetVigraImageFilter();
91 // now the raw formats
92 std::vector<std::string> exts = GetRawExtensions();
93 filterString.Append(_("Raw files")).Append("|");
94 for (auto& ext : exts)
95 {
96 filterString.Append(GetFilterExtensions(ext)).Append(";");
97 };
98 // remove last character == ";"
99 filterString.RemoveLast();
100 filterString.Append("|");
101 // now add some image format at its own
102 filterString.Append(_("JPEG files (*.jpg,*.jpeg)")).Append("|").Append(GetFilterExtensions("jpg")).Append(";").Append(GetFilterExtensions("jpeg"));
103 filterString.Append("|").Append(_("TIFF files (*.tif,*.tiff)")).Append("|").Append(GetFilterExtensions("tif")).Append(";").Append(GetFilterExtensions("tiff"));
104 filterString.Append("|").Append(_("PNG files (*.png)")).Append("|").Append(GetFilterExtensions("png"));
105 filterString.Append("|").Append(_("HDR files (*.hdr)")).Append("|").Append(GetFilterExtensions("hdr"));
106 filterString.Append("|").Append(_("EXR files (*.exr)")).Append("|").Append(GetFilterExtensions("exr"));
107 return filterString;
108 };
109
IsRawExtension(const wxString & testExt)110 bool IsRawExtension(const wxString& testExt)
111 {
112 std::vector<std::string> rawExts = GetRawExtensions();
113 for (auto& ext : rawExts)
114 {
115 if (testExt.CmpNoCase(wxString(ext.c_str(), wxConvLocal)) == 0)
116 {
117 return true;
118 };
119 };
120 return false;
121 };
122
123 #if defined __WXMAC__ || defined __WXOSX_COCOA__
124
125 #include <CoreFoundation/CFBundle.h>
126 #include "wx/osx/core/cfstring.h"
127 #include <iostream>
128 #include <stdio.h>
129 #include "wx/utils.h"
130
131 using namespace std;
132
133 // note this is a "create" function for ownership
MacCreateCFStringWithWxString(const wxString & string)134 CFStringRef MacCreateCFStringWithWxString(const wxString& string)
135 {
136 return CFStringCreateWithCString(NULL,
137 (const char*)string.mb_str(wxConvUTF8),
138 kCFStringEncodingUTF8);
139
140 }
141
MacGetPathToMainExecutableFileOfBundle(CFStringRef bundlePath)142 wxString MacGetPathToMainExecutableFileOfBundle(CFStringRef bundlePath)
143 {
144 wxString theResult = wxT("");
145
146 CFURLRef bundleURL = CFURLCreateWithFileSystemPath(NULL, bundlePath, kCFURLPOSIXPathStyle, TRUE);
147
148 if(bundleURL == NULL)
149 {
150 DEBUG_INFO("Mac: CFURL from string (" << bundlePath << ") failed." );
151 return theResult;
152 }
153
154 CFBundleRef bundle = CFBundleCreate(NULL, bundleURL);
155 CFRelease(bundleURL);
156
157 if(bundle == NULL)
158 {
159 DEBUG_INFO("Mac: CFBundleCreate (" << bundlePath << " ) failed" );
160 }
161 else
162 {
163 CFURLRef PTOurl = CFBundleCopyExecutableURL(bundle);
164 CFRelease( bundle );
165 if(PTOurl == NULL)
166 {
167 DEBUG_INFO("Mac: Cannot locate the executable in the bundle.");
168 }
169 else
170 {
171 CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
172 CFRelease( PTOurl );
173 if(PTOAbsURL == NULL)
174 {
175 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
176 }
177 else
178 {
179 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
180 CFRelease( PTOAbsURL );
181 if(pathInCFString == NULL)
182 {
183 DEBUG_INFO("Mac: Failed to get URL in CFString");
184 }
185 else
186 {
187 CFRetain( pathInCFString );
188 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
189 DEBUG_INFO("Mac: the executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
190 }
191 }
192 }
193 }
194 return theResult;
195 }
196
MacGetPathToMainExecutableFileOfRegisteredBundle(CFStringRef BundleIdentifier)197 wxString MacGetPathToMainExecutableFileOfRegisteredBundle(CFStringRef BundleIdentifier)
198 {
199 wxString theResult = wxT("");
200
201 FSRef appRef;
202 CFURLRef bundleURL;
203 FSRef actuallyLaunched;
204 OSStatus err;
205 FSRef documentArray[1]; // Don't really need an array if we only have 1 item
206 LSLaunchFSRefSpec launchSpec;
207 //Boolean isDir;
208
209 err = LSFindApplicationForInfo(kLSUnknownCreator,
210 CFSTR("net.sourceforge.hugin.PTBatcherGUI"),
211 NULL,
212 &appRef,
213 &bundleURL);
214 if (err != noErr) {
215 // error, can't find PTBatcherGUI
216 cout << "PTBatcherGui check failed \n" << endl;
217 wxMessageBox(wxString::Format(_("External program %s not found in the bundle, reverting to system path"), wxT("open")), _("Error"));
218 }
219 if(bundleURL == NULL)
220 {
221 DEBUG_INFO("Mac: CFURL from string (" << bundleURL << ") failed." );
222 return theResult;
223 }
224
225 CFBundleRef bundle = CFBundleCreate(NULL, bundleURL);
226 CFRelease(bundleURL);
227
228 if(bundle == NULL)
229 {
230 DEBUG_INFO("Mac: CFBundleCreate (" << bundleURL << " ) failed" );
231 }
232 else
233 {
234 CFURLRef PTOurl = CFBundleCopyExecutableURL(bundle);
235 CFRelease( bundle );
236 if(PTOurl == NULL)
237 {
238 DEBUG_INFO("Mac: Cannot locate the executable in the bundle.");
239 }
240 else
241 {
242 CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
243 CFRelease( PTOurl );
244 if(PTOAbsURL == NULL)
245 {
246 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
247 }
248 else
249 {
250 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
251 CFRelease( PTOAbsURL );
252 if(pathInCFString == NULL)
253 {
254 DEBUG_INFO("Mac: Failed to get URL in CFString");
255 }
256 else
257 {
258 CFRetain( pathInCFString );
259 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
260 DEBUG_INFO("Mac: the executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
261 }
262 }
263 }
264 }
265 cout << "PTBatcherGui check returned value " << theResult << "\n" << endl;
266 return theResult;
267 }
268
269 #if defined MAC_SELF_CONTAINED_BUNDLE
270
MacGetPathToBundledAppMainExecutableFile(CFStringRef appname)271 wxString MacGetPathToBundledAppMainExecutableFile(CFStringRef appname)
272 {
273 wxString theResult = wxT("");
274
275 CFBundleRef mainbundle = CFBundleGetMainBundle();
276 if(mainbundle == NULL)
277 {
278 DEBUG_INFO("Mac: Not bundled");
279 }
280 else
281 {
282 CFURLRef XRCurl = CFBundleCopyResourceURL(mainbundle, appname, NULL, NULL);
283 if(XRCurl == NULL)
284 {
285 DEBUG_INFO("Mac: Cannot locate the bundle in bundle.");
286 }
287 else
288 {
289 CFBundleRef bundledBundle = CFBundleCreate(NULL, XRCurl);
290 CFRelease( XRCurl );
291
292 if(bundledBundle == NULL)
293 {
294 DEBUG_INFO("Mac: Not bundled");
295 }
296 else
297 {
298 CFURLRef PTOurl = CFBundleCopyExecutableURL(bundledBundle);
299 CFRelease( bundledBundle );
300
301 if(PTOurl == NULL)
302 {
303 DEBUG_INFO("Mac: Cannot locate the executable in the bundle.");
304 }
305 else
306 {
307 CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
308 CFRelease( PTOurl );
309 if(PTOAbsURL == NULL)
310 {
311 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
312 }
313 else
314 {
315 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
316 CFRelease( PTOAbsURL );
317 if(pathInCFString == NULL)
318 {
319 DEBUG_INFO("Mac: Failed to get URL in CFString");
320 }
321 else
322 {
323 CFRetain( pathInCFString );
324 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
325 DEBUG_INFO("Mac: the executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
326 }
327 }
328 }
329 }
330 }
331 }
332 return theResult;
333 }
334
MacGetPathToBundledResourceFile(CFStringRef filename)335 wxString MacGetPathToBundledResourceFile(CFStringRef filename)
336 {
337 wxString theResult = wxT("");
338
339 CFBundleRef mainbundle = CFBundleGetMainBundle();
340 if(mainbundle == NULL)
341 {
342 DEBUG_INFO("Mac: Not bundled");
343 }
344 else
345 {
346 CFURLRef XRCurl = CFBundleCopyResourceURL(mainbundle, filename, NULL, NULL);
347 if(XRCurl == NULL)
348 {
349 DEBUG_INFO("Mac: Cannot locate the file in bundle.");
350 }
351 else
352 {
353 CFStringRef pathInCFString = CFURLCopyFileSystemPath(XRCurl, kCFURLPOSIXPathStyle);
354 CFRelease( XRCurl );
355 if(pathInCFString == NULL)
356 {
357 DEBUG_INFO("Mac: Failed to get URL in CFString");
358 }
359 else
360 {
361 CFRetain( pathInCFString );
362 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
363 DEBUG_INFO("Mac: the resource file's path in the application bundle: " << theResult.mb_str(wxConvLocal));
364 }
365 }
366 }
367 return theResult;
368 }
369
MacGetPathToBundledFrameworksDirectory()370 wxString MacGetPathToBundledFrameworksDirectory()
371 {
372 wxString theResult = wxT("");
373
374 CFBundleRef mainbundle = CFBundleGetMainBundle();
375 if(mainbundle == NULL)
376 {
377 DEBUG_INFO("Mac: Not bundled");
378 }
379 else
380 {
381 CFURLRef XRCurl = CFBundleCopyBundleURL(mainbundle);
382 if(XRCurl == NULL)
383 {
384 DEBUG_INFO("Mac: Cannot locate the file in bundle.");
385 }
386 else
387 {
388 CFStringRef pathInCFString = CFURLCopyFileSystemPath(XRCurl, kCFURLPOSIXPathStyle);
389 CFRelease( XRCurl );
390 if(pathInCFString == NULL)
391 {
392 DEBUG_INFO("Mac: Failed to get URL in CFString");
393 }
394 else
395 {
396 CFRetain( pathInCFString );
397 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
398 DEBUG_INFO("Mac: the Frameworks file's path in the application bundle: " << theResult.mb_str(wxConvLocal));
399 }
400 }
401 }
402 return theResult + wxT("/Contents/Frameworks");
403 }
404
MacGetPathToBundledExecutableFile(CFStringRef filename)405 wxString MacGetPathToBundledExecutableFile(CFStringRef filename)
406 {
407 wxString theResult = wxT("");
408
409 CFBundleRef mainbundle = CFBundleGetMainBundle();
410 if(mainbundle == NULL)
411 {
412 DEBUG_INFO("Mac: Not bundled");
413 }
414 else
415 {
416 CFURLRef PTOurl = CFBundleCopyAuxiliaryExecutableURL(mainbundle, filename);
417 if(PTOurl == NULL)
418 {
419 DEBUG_INFO("Mac: Cannot locate the file in the bundle.");
420 }
421 else
422 {
423 CFURLRef PTOAbsURL = CFURLCopyAbsoluteURL( PTOurl );
424 if(PTOAbsURL == NULL)
425 {
426 DEBUG_INFO("Mac: Cannot convert the file path to absolute");
427 }
428 else
429 {
430 CFStringRef pathInCFString = CFURLCopyFileSystemPath(PTOAbsURL, kCFURLPOSIXPathStyle);
431 CFRelease( PTOAbsURL );
432 if(pathInCFString == NULL)
433 {
434 DEBUG_INFO("Mac: Failed to get URL in CFString");
435 }
436 else
437 {
438 CFRetain( pathInCFString );
439 theResult = wxCFStringRef(pathInCFString).AsString(wxLocale::GetSystemEncoding());
440 DEBUG_INFO("Mac: executable's full path in the application bundle: " << theResult.mb_str(wxConvLocal));
441 }
442 }
443 CFRelease( PTOurl );
444 }
445 }
446 return theResult;
447 }
448
MacGetPathToUserDomainTempDir()449 wxString MacGetPathToUserDomainTempDir()
450 {
451 wxString tmpDirPath = wxT("");
452
453 FSRef tempDirRef;
454 OSErr err = FSFindFolder(kUserDomain, kTemporaryFolderType, kCreateFolder, &tempDirRef);
455 if (err == noErr)
456 {
457 CFURLRef tempDirURL = CFURLCreateFromFSRef(kCFAllocatorSystemDefault, &tempDirRef);
458 if (tempDirURL != NULL)
459 {
460 CFStringRef tmpPath = CFURLCopyFileSystemPath(tempDirURL, kCFURLPOSIXPathStyle);
461 CFRetain(tmpPath);
462 tmpDirPath = wxCFStringRef(tmpPath).AsString(wxLocale::GetSystemEncoding());
463 CFRelease(tempDirURL);
464 }
465 }
466
467 return tmpDirPath;
468 }
469
MacGetPathToUserAppSupportAutoPanoFolder()470 wxString MacGetPathToUserAppSupportAutoPanoFolder()
471 {
472 wxString appSupportAutoPanoFolder = wxT("");
473
474 FSRef appSupportFolder;
475 OSErr err = FSFindFolder(kUserDomain,kApplicationSupportFolderType,kDontCreateFolder,&appSupportFolder);
476 if( err == noErr)
477 {
478 CFURLRef appSupportFolderURL = CFURLCreateFromFSRef(kCFAllocatorDefault,&appSupportFolder);
479 CFURLRef appSupportHugin = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,appSupportFolderURL,CFSTR("Hugin"),true);
480 CFURLRef autopanoURL = CFURLCreateCopyAppendingPathComponent(kCFAllocatorDefault,appSupportHugin,CFSTR("Autopano"),true);
481 CFStringRef tmpPath = CFURLCopyFileSystemPath(autopanoURL, kCFURLPOSIXPathStyle);
482 CFRetain(tmpPath);
483 appSupportAutoPanoFolder = wxCFStringRef(tmpPath).AsString(wxLocale::GetSystemEncoding());
484 CFRelease(autopanoURL);
485 }
486 return appSupportAutoPanoFolder;
487 }
488
489
490 #endif // MAC_SELF_CONTAINED_BUNDLE
491
492 #endif // __WXMAC__
493
getInvalidCharacters()494 const wxString getInvalidCharacters()
495 {
496 #if defined __WXMSW__
497 // the characters :"*?<>| are not allowed in filenames, these are handled well by the file dialog
498 // all other characters should work
499 return wxEmptyString;
500 #else
501 // the characters =;:% does not work with the makefile
502 // we are also rejecting the characters <>*?| which are principally allowed in filenames but will probably make problems when used
503 // the double quote does not work with the panotools file format, so also reject
504 //@BUG tilde ~ and backslash \ are not working with vigraimpex, if this works again these characters can be removed from the list
505 return wxT("*?<>|\"\\~");
506 #endif
507 };
508
containsInvalidCharacters(const wxString stringToTest)509 bool containsInvalidCharacters(const wxString stringToTest)
510 {
511 if(stringToTest.IsEmpty())
512 return false;
513 wxString forbiddenChars=getInvalidCharacters();
514 for(unsigned int j=0;j<forbiddenChars.size();j++)
515 {
516 if(stringToTest.Find(forbiddenChars[j])!=wxNOT_FOUND)
517 return true;
518 };
519 return false;
520 };
521
ShowFilenameWarning(wxWindow * parent,const wxArrayString filelist)522 void ShowFilenameWarning(wxWindow* parent, const wxArrayString filelist)
523 {
524 wxDialog dlg;
525 wxXmlResource::Get()->LoadDialog(&dlg, parent, wxT("dlg_warning_filename"));
526 XRCCTRL(dlg, "dlg_warning_text", wxStaticText)->SetLabel(wxString::Format(_("The filename(s) contains one of the following invalid characters: %s\nHugin can not work with these filenames. Please rename your file(s) and try again."), getInvalidCharacters().c_str()));
527 XRCCTRL(dlg, "dlg_warning_list", wxListBox)->Append(filelist);
528 dlg.Fit();
529 dlg.CenterOnScreen();
530 dlg.ShowModal();
531 };
532
533 #if wxUSE_ON_FATAL_EXCEPTION
GenerateReport(wxDebugReport::Context ctx)534 void GenerateReport(wxDebugReport::Context ctx)
535 {
536 //from the debugrpt sample inspired
537 wxDebugReportCompress report;
538 report.AddAll(ctx);
539 if (wxDebugReportPreviewStd().Show(report))
540 {
541 if (report.Process())
542 {
543 wxLogMessage(_("Debug report generated in \"%s\"."), report.GetCompressedFileName().c_str());
544 report.Reset();
545 };
546 };
547 };
548 #endif
549