diff --git a/CMakeLists.txt b/CMakeLists.txt index b0e3c8672df5ca74beac0db6f1ce6056df770a5a..be7679a63e50d36e2db7cdf4aab046396e4ca0b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -94,7 +94,7 @@ opt(TETGEN_OLD "Enable older version of Tetgen" OFF) opt(VORO3D "Enable Voro3D (for hex meshing, experimental)" ${DEFAULT}) opt(WRAP_JAVA "Enable generation of Java wrappers (experimental)" OFF) opt(WRAP_PYTHON "Enable generation of Python wrappers" OFF) -opt(ZIPPER "Enable zip compression/decompression" OFF) +opt(ZIPPER "Enable Zip file compression/decompression" OFF) set(GMSH_MAJOR_VERSION 2) set(GMSH_MINOR_VERSION 10) diff --git a/Common/OS.cpp b/Common/OS.cpp index d78fb9f5153c14ef2fced9026668c67ebeba193d..62e860c7b152364e81a0f097a866006da7d31c0c 100644 --- a/Common/OS.cpp +++ b/Common/OS.cpp @@ -19,6 +19,13 @@ #include "StringUtils.h" #include "Context.h" +#if defined(HAVE_ZIPPER) +#include <iostream> +#include <fstream> +#include "zipper.h" +#include "unzipper.h" +#endif + #if defined(__APPLE__) #include <sys/sysctl.h> #include <mach-o/dyld.h> @@ -668,3 +675,39 @@ void RedirectIOToConsole() std::ios::sync_with_stdio(); #endif } + +void UnzipFile(const std::string &fileName, const std::string &prependDir) +{ +#if defined(HAVE_ZIPPER) + std::string dir = prependDir; + if(dir.size() && dir[dir.size()-1] != '/' && dir[dir.size()-1] != '\\') + dir.push_back('/'); + + ziputils::unzipper zipFile; + zipFile.open(fileName.c_str()); + std::vector<std::string> dirnames = zipFile.getFolders(); + for (std::vector<std::string>::const_iterator it = dirnames.begin(); + it != dirnames.end(); it++){ + std::string folder = dir + *it; + Msg::Info("Creating folder `%s'", folder.c_str()); + CreatePath(folder); + } + std::vector<std::string> filenames = zipFile.getFilenames(); + for (std::vector<std::string>::const_iterator it = filenames.begin(); + it != filenames.end(); it++){ + zipFile.openEntry(it->c_str()); + std::string name = dir + *it; + Msg::Info("Extracting file `%s'", name.c_str()); + std::ofstream ofs; + ofs.open(name.c_str()); + if(ofs.is_open()){ + zipFile >> ofs; + ofs.close(); + } + else + Msg::Error("Could not create file `%s'", name.c_str()); + } +#else + Msg::Error("Gmsh must be compiled with Zipper support to extract zip files"); +#endif +} diff --git a/Common/OS.h b/Common/OS.h index 17632f89ddeba60bacc3c0a76d2c55fee1b886b3..081dc222991f395c32df88a748b42cde6d0004f8 100644 --- a/Common/OS.h +++ b/Common/OS.h @@ -9,6 +9,7 @@ #include <string> #include <stdio.h> +FILE *Fopen(const char* f, const char *mode); const char *GetEnvironmentVar(const char *var); void SetEnvironmentVar(const char *var, const char *val); double GetTimeInSeconds(); @@ -31,6 +32,6 @@ int SystemCallExe(const std::string &exe, const std::string &argsOrCommand, bool blocking=false); std::string GetCurrentWorkdir(); void RedirectIOToConsole(); -FILE *Fopen(const char* f, const char *mode); +void UnzipFile(const std::string &fileName, const std::string &prependDir=""); #endif diff --git a/contrib/mobile/iOS/Onelab.xcodeproj/project.pbxproj b/contrib/mobile/iOS/Onelab.xcodeproj/project.pbxproj index 5617224b2c0398730ef325fba3d280adb9710ce7..ba27239b771e4a06c3611d72375133a151482e6c 100644 --- a/contrib/mobile/iOS/Onelab.xcodeproj/project.pbxproj +++ b/contrib/mobile/iOS/Onelab.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 2901F1211BB0086C004C328B /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2901F1201BB0086C004C328B /* libz.dylib */; }; 2907CCEC193DE6560011341A /* icon_onelab.png in Resources */ = {isa = PBXBuildFile; fileRef = 2907CCEB193DE6560011341A /* icon_onelab.png */; }; 2988FF1E18E59558001435B6 /* libf2cblas.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2988FF1C18E59558001435B6 /* libf2cblas.a */; }; 2988FF1F18E59558001435B6 /* libf2clapack.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2988FF1D18E59558001435B6 /* libf2clapack.a */; }; @@ -51,6 +52,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2901F1201BB0086C004C328B /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; }; 2907CCEB193DE6560011341A /* icon_onelab.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_onelab.png; sourceTree = "<group>"; }; 2988FF1C18E59558001435B6 /* libf2cblas.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libf2cblas.a; path = ../../frameworks_ios/libf2cblas.a; sourceTree = "<group>"; }; 2988FF1D18E59558001435B6 /* libf2clapack.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libf2clapack.a; path = ../../frameworks_ios/libf2clapack.a; sourceTree = "<group>"; }; @@ -122,6 +124,7 @@ files = ( 2988FF1E18E59558001435B6 /* libf2cblas.a in Frameworks */, 2988FF1F18E59558001435B6 /* libf2clapack.a in Frameworks */, + 2901F1211BB0086C004C328B /* libz.dylib in Frameworks */, 9C2C3A20187FDF9900E87F78 /* libstdc++.dylib in Frameworks */, 9C2C3A1E187FDF9200E87F78 /* libc++.dylib in Frameworks */, 9C96089D1712C7F600E1D4A0 /* QuartzCore.framework in Frameworks */, @@ -170,6 +173,7 @@ 9C9608391712C16300E1D4A0 /* Frameworks */ = { isa = PBXGroup; children = ( + 2901F1201BB0086C004C328B /* libz.dylib */, 9C1B9911194F4E0400507EFD /* slepc.framework */, 2988FF1C18E59558001435B6 /* libf2cblas.a */, 2988FF1D18E59558001435B6 /* libf2clapack.a */, diff --git a/contrib/mobile/iOS/Onelab/AppDelegate.mm b/contrib/mobile/iOS/Onelab/AppDelegate.mm index 64579b9e7ebce4cbc3eb2ad829e2dc3bc1bacc18..f155763c203b73b77d9a1a2a738e9d3be31e9c9f 100644 --- a/contrib/mobile/iOS/Onelab/AppDelegate.mm +++ b/contrib/mobile/iOS/Onelab/AppDelegate.mm @@ -28,6 +28,17 @@ else{ NSLog(@"Leaving models as-is (version %@)", prefsv); } + + // Check if there is a model to open + NSURL* url = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey]; + [Utils openModelURL:url]; + + return YES; +} + +- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation +{ + [Utils openModelURL:url]; return YES; } diff --git a/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad.png b/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad.png index a375bd3d75634a444e0847add7345be901bf7a4e..a3d380259339378786654f875763943625e14c54 100644 Binary files a/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad.png and b/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad.png differ diff --git a/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad_retina.png b/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad_retina.png index ce69f13ee2cc67fa2e3bfcaa7adf7acebb9e066e..9d32334991017d7ef43cb57141a76ee95d529fb4 100644 Binary files a/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad_retina.png and b/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_ipad_retina.png differ diff --git a/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_iphone_retina.png b/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_iphone_retina.png index 4ad538bdd6d17c10ee4fa1e2cf0003161b255228..f924b3cec5c647292b37c546989a775979978143 100644 Binary files a/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_iphone_retina.png and b/contrib/mobile/iOS/Onelab/Images.xcassets/AppIcon.appiconset/icon_app_iphone_retina.png differ diff --git a/contrib/mobile/iOS/Onelab/Onelab-Info.plist b/contrib/mobile/iOS/Onelab/Onelab-Info.plist index e3b855347ce97ef915d99ce9e03ef3b0f585850b..56781a8f5d30bb264254dfdb7fe3a0d8d393f817 100644 --- a/contrib/mobile/iOS/Onelab/Onelab-Info.plist +++ b/contrib/mobile/iOS/Onelab/Onelab-Info.plist @@ -68,5 +68,27 @@ <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> + <key>CFBundleDocumentTypes</key> + <array> + <dict> + <key>CFBundleTypeName</key> + <string>Zip archive</string> + <key>CFBundleTypeRole</key> + <string>Editor</string> + <key>LSItemContentTypes</key> + <array> + <string>com.pkware.zip-archive</string> + </array> + <key>UTTypeTagSpecification</key> + <dict> + <key>public.filename-extension</key> + <string>zip</string> + <key>public.mime-type</key> + <string>application/zip</string> + </dict> + <key>LSHandlerRank</key> + <string>Owner</string> + </dict> + </array> </dict> </plist> diff --git a/contrib/mobile/iOS/Onelab/Utils.h b/contrib/mobile/iOS/Onelab/Utils.h index 448225c7a40f27ad8c0dd1eb83b10c0514ddc88d..8c1db0a7b7314017e06b5e7e4917a9a7e7d7aa49 100644 --- a/contrib/mobile/iOS/Onelab/Utils.h +++ b/contrib/mobile/iOS/Onelab/Utils.h @@ -4,8 +4,7 @@ + (NSString *) getApplicationDocumentsDirectory; + (void) copyRes; - ++ (void) openModelURL:(NSURL*)url; + (id) traverseResponderChainForUIViewController:(UIView *)v; - @end diff --git a/contrib/mobile/iOS/Onelab/Utils.mm b/contrib/mobile/iOS/Onelab/Utils.mm index f76a002ff5ca7575fae207dcf0008752a353d8df..e1525274c615d16c0cd083fa64643577a24494b6 100644 --- a/contrib/mobile/iOS/Onelab/Utils.mm +++ b/contrib/mobile/iOS/Onelab/Utils.mm @@ -1,5 +1,7 @@ #import "Utils.h" +#include <gmsh/OS.h> + @implementation Utils + (NSString *) getApplicationDocumentsDirectory @@ -28,6 +30,24 @@ } } ++ (void) openModelURL:(NSURL*)url +{ + if(!url) return; + NSString *filepath = [url path]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *docPath = [paths objectAtIndex:0]; //Get the docs directory + NSString *extension = [filepath pathExtension]; + if([extension isEqualToString:@"zip"] || [extension isEqualToString:@"ZIP"]){ + NSLog(@"Unzipping %@", filepath); + UnzipFile([filepath UTF8String], [docPath UTF8String]); + NSLog(@"Removing %@", filepath); + [[NSFileManager defaultManager] removeItemAtPath:filepath error:nil]; + } + else{ + NSLog(@"Unknown model file extension: only .zip files are currently accepted"); + } +} + + (UIViewController *) traverseResponderChainForUIViewController:(UIView *)v { id nextResponder = [v nextResponder]; diff --git a/contrib/zipper/unzipper.cpp b/contrib/zipper/unzipper.cpp index f66db1a1a3c498a5b7d3dab85c7efcf2efe7e8dc..e39367c155534cbd39b41a9ef21677c45a9737e2 100644 --- a/contrib/zipper/unzipper.cpp +++ b/contrib/zipper/unzipper.cpp @@ -162,7 +162,7 @@ namespace ziputils } } - // Dump the currently open entry to the uotput stream + // Dump the currently open entry to the output stream unzipper& unzipper::operator>>( std::ostream& os ) { if ( isOpenEntry() ) diff --git a/utils/icons/gmsh.xcf b/utils/icons/gmsh.xcf index db573a58e8a4ef177907699fab08cc0c2430f814..532271281a0daa46813ede1ccebced73dda611a7 100644 Binary files a/utils/icons/gmsh.xcf and b/utils/icons/gmsh.xcf differ diff --git a/utils/icons/gmsh_mobile_1024x1024.png b/utils/icons/gmsh_mobile_1024x1024.png index 5959848fa2bc802ba0c26b9521e54d08ae8afca6..73ecd184873c9406528367771c9743650e03a09c 100644 Binary files a/utils/icons/gmsh_mobile_1024x1024.png and b/utils/icons/gmsh_mobile_1024x1024.png differ