Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit da9bff7
Author: Tyler Burgett <[email protected]>
Date:   Wed Aug 11 13:10:49 2021 -0600

    Fix for URL check. Button style changes. Better handling for images when saving attachments to a new point.

commit f3c3e62
Author: Tyler Burgett <[email protected]>
Date:   Mon Jul 5 17:27:27 2021 -0600

    Fix for an inconsistancy when saving points to a new feature layer. Added compass mode to the map. Changed the default map pin style to match MAGE.

commit 809a613
Author: Tyler Burgett <[email protected]>
Date:   Fri Jun 18 14:25:40 2021 -0600

    Added code for getting and views for viewing attachments for map features. Bug fixes for deleting geopackages, URL validation, checks for geopackages with incorrect SRS IDs.

commit 2dd99c2
Author: Tyler Burgett <[email protected]>
Date:   Thu Apr 15 11:36:09 2021 -0600

    Design updates
  • Loading branch information
tyburg committed Aug 12, 2021
1 parent d5c71f0 commit 3b4bf00
Show file tree
Hide file tree
Showing 44 changed files with 1,216 additions and 128 deletions.
Binary file modified mapcache-ios-geopackage.sketch
Binary file not shown.
44 changes: 40 additions & 4 deletions mapcache-ios.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions mapcache-ios/Images.xcassets/GPSHeading.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "GPS-heading.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions mapcache-ios/Images.xcassets/camera.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "camera.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions mapcache-ios/Images.xcassets/gallery.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "gallery.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions mapcache-ios/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>NSCameraUsageDescription</key>
<string>Attach photos to your pin</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>To view your position on the map allow MapCache to find your location. </string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Attach photos to your pin</string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
Expand Down
8 changes: 4 additions & 4 deletions mapcache-ios/data/MCGeoPackageRepository.m
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,9 @@ - (BOOL) createFeatueLayerIn:(NSString *)database withGeomertyColumns:(GPKGGeome
// TODO handle this
NSLog(@"There was a problem creating the layer, %@", e.reason);
didCreateLayer = NO;
[MCUtils showMessageWithDelegate:self
andTitle:[NSString stringWithFormat:@"Unable to create feature layer"]
andMessage:[NSString stringWithFormat:@"%@", e.reason]];
} @finally {
[geoPackage close];
[self regenerateDatabaseList];
Expand Down Expand Up @@ -414,9 +417,6 @@ - (BOOL)saveRow:(GPKGFeatureRow *)featureRow {
[_activeDatabases addTable:table];
}

self.selectedLayerName = @"";
self.selectedGeoPackageName = @"";

} @catch (NSException *e) {
NSLog(@"Problem while saving point data: %@", e.reason);
saved = NO;
Expand Down Expand Up @@ -584,7 +584,7 @@ - (BOOL)addColumn:(GPKGFeatureColumn *)featureColumn to:(MCTable *)table {
[self.activeDatabases addTable:[updatedDatabase tableNamed:table.name]];
}
} @catch (NSException *e) {
NSLog(@"MCGeoPackageRepository - Probem renaiming table: %@", e.reason);
NSLog(@"MCGeoPackageRepository - Problem renaming table: %@", e.reason);
} @finally {
if (geoPackage != nil) {
[geoPackage close];
Expand Down
129 changes: 129 additions & 0 deletions mapcache-ios/data/MCMediaUtility.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
//
// MCMediaUtility.swift
// mapcache-ios
//
// Created by Tyler Burgett on 4/22/21.
// Copyright © 2021 NGA. All rights reserved.
//

import Foundation


@objc class MCMediaUtility: NSObject {
@objc static let shared = MCMediaUtility()
let manager = GPKGGeoPackageFactory.manager()
let mediaTableName = "gpkg_media"
let idColumnName = "id"
let relatedIdColumnName = "related_id"
let dataColumnName = "data"
let contentTypeColumnName = "content_type"

private override init() {
super.init()
}


@objc func mediaRelationsFor(geoPackageName: String, row:GPKGUserRow) -> [GPKGUserRow] {
let geoPackage = manager?.open(geoPackageName)
let relatedTables = GPKGRelatedTablesExtension.init(geoPackage: geoPackage)

if (relatedTables?.has() != nil) {
print("Have related tables!")
if let featureDao:GPKGFeatureDao = geoPackage?.featureDao(withTableName: row.tableName()) {
let relationships:[GPKGExtendedRelation] = (relatedTables?.relationships())!
for relationship:GPKGExtendedRelation in relationships {
print("base table name: \(relationship.baseTableName) related table name: \(relationship.relatedTableName) mapping table name: \(relationship.mappingTableName)")
if row.tableName() == relationship.baseTableName && relationship.relatedTableName == self.mediaTableName {
if let mappedIDs = relatedTables?.mappings(for: relationship, withBaseId: row.idValue()) {
if let mediaDao = relatedTables?.mediaDao(for: relationship) {
if let mediaRows = mediaDao.rows(withIds: mappedIDs) {
return mediaRows
}
}
}
}
}
}
}

return []
}


@objc func saveAttachmentsFor(row: GPKGUserRow, media:(NSArray), databaseName:String) {
if let geoPackage = self.manager?.open(databaseName) {
if let relatedTables = GPKGRelatedTablesExtension.init(geoPackage: geoPackage) {
let mappingTableName = row.tableName() + "_" + self.mediaTableName
var mediaTable:GPKGMediaTable = GPKGMediaTable.init()

if !relatedTables.has() || !geoPackage.isTable(self.mediaTableName) || !geoPackage.isTable(mappingTableName) {
// Create the media table
let columns = NSMutableArray()

if !geoPackage.isTable(self.mediaTableName) {
mediaTable = GPKGMediaTable.create(with: GPKGMediaTableMetadata.create(withTable: self.mediaTableName, andAdditionalColumns: (columns as! [GPKGUserCustomColumn])))
} else {
if let mediaDao = relatedTables.mediaDao(forTableName: self.mediaTableName) {
mediaTable = mediaDao.mediaTable()
}
}

if !geoPackage.isTable(mappingTableName) {
let mappingColumns = NSMutableArray()
let userMappingTable = GPKGUserMappingTable.create(withName: mappingTableName, andAdditionalColumns: (mappingColumns as! [GPKGUserCustomColumn]))
// relate the tables
relatedTables.addMediaRelationship(withBaseTable: row.tableName(), andMediaTable: mediaTable, andUserMappingTable: userMappingTable)
}
}

if let mediaDao = relatedTables.mediaDao(forTableName: self.mediaTableName) {
// do some saving
for m in media {
if let image:UIImage = (m as? UIImage)?.rotateImage() {
if let data:Data = image.pngData() {
let contentType = "image/png"
var mediaRow:GPKGMediaRow = mediaDao.newRow()
mediaRow.setData(data)
mediaRow.setContentType(contentType)
//mediaRow.setId(NSNumber.init(value: mediaDao.create(mediaRow)))
mediaDao.create(mediaRow)

let mappingTableName = row.tableName() + "_" + self.mediaTableName
let userMappingDao = relatedTables.mappingDao(forTableName: mappingTableName)
let userMappingRow = userMappingDao?.newRow()
userMappingRow?.setBaseId(row.idValue())
userMappingRow?.setRelatedId(mediaRow.idValue())
userMappingDao?.create(userMappingRow)
}
}
}
}
}
}
}


@objc func deleteAttachment(geoPackageName: String, row:GPKGUserRow, mediaRow:GPKGMediaRow) -> Bool {
let geoPackage = manager?.open(geoPackageName)
let relatedTables = GPKGRelatedTablesExtension.init(geoPackage: geoPackage)

if (relatedTables?.has() != nil) {
print("Have related tables!")
if let featureDao:GPKGFeatureDao = geoPackage?.featureDao(withTableName: row.tableName()) {
let relationships:[GPKGExtendedRelation] = (relatedTables?.relationships())!
for relationship:GPKGExtendedRelation in relationships {
if row.tableName() == relationship.baseTableName {
if let mappedIDs = relatedTables?.mappings(for: relationship, withBaseId: row.idValue()) {
if let mediaDao = relatedTables?.mediaDao(for: relationship) {
return mediaDao.delete(mediaRow) > 0
}
}
}
}
}
}

return false
}
}

105 changes: 63 additions & 42 deletions mapcache-ios/data/MCTileServerRepository.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ import Foundation
if (tryXYZ) {
URLSession.shared.downloadTask(with: url) { (location, response, error) in
do {
if let e = error {
tileServer.serverType = .error
let result = MCTileServerResult.init(tileServer, self.generateError(message: e.localizedDescription, errorType: MCServerErrorType.MCTileServerNoResponse))
completion(result)
return
}

guard let tile = UIImage.init(data: try Data.init(contentsOf: location!)) else {
tileServer.serverType = .error
let result = MCTileServerResult.init(tileServer, self.generateError(message: "Unable to get tile", errorType: MCServerErrorType.MCNoData))
Expand Down Expand Up @@ -121,55 +128,69 @@ import Foundation


@objc public func getCapabilites(url:String, completion: @escaping (MCTileServerResult) -> Void) {
if let wmsURL = URL.init(string: url) {
let baseURL:String = wmsURL.scheme! + "://" + wmsURL.host! + wmsURL.path
let tileServer = MCTileServer.init(serverName: self.urlString)
self.layers = []
guard let wmsURL:URL = URL.init(string: url) else {
let tileServer = MCTileServer.init(serverName: urlString)
tileServer.serverType = .error
let result = MCTileServerResult.init(tileServer, self.generateError(message: "Invalid URL", errorType: MCServerErrorType.MCURLInvalid))

completion(result)
return
}

if wmsURL.host == nil || wmsURL.scheme == nil {
let tileServer = MCTileServer.init(serverName: urlString)
tileServer.serverType = .error
let result = MCTileServerResult.init(tileServer, self.generateError(message: "Invalid URL", errorType: MCServerErrorType.MCURLInvalid))

completion(result)
return
}

let baseURL:String = wmsURL.scheme! + "://" + wmsURL.host! + wmsURL.path
let tileServer = MCTileServer.init(serverName: self.urlString)
self.layers = []

var builtURL = URLComponents(string: baseURL)
builtURL?.queryItems = [
URLQueryItem(name: "request", value: "GetCapabilities"),
URLQueryItem(name: "service", value: "WMS"),
URLQueryItem(name: "version", value: "1.3.0")
]

let task = URLSession.shared.dataTask(with: (builtURL?.url)!) { data, response, error in
guard let data = data, error == nil else {
completion(MCTileServerResult.init(tileServer, self.generateError(message: error?.localizedDescription ?? "Server error", errorType: .MCTileServerParseError)))
return
}

var builtURL = URLComponents(string: baseURL)
builtURL?.queryItems = [
URLQueryItem(name: "request", value: "GetCapabilities"),
URLQueryItem(name: "service", value: "WMS"),
URLQueryItem(name: "version", value: "1.3.0")
]
let parser = XMLParser(data: data)
parser.delegate = self

let task = URLSession.shared.dataTask(with: (builtURL?.url)!) { data, response, error in
guard let data = data, error == nil else {
completion(MCTileServerResult.init(tileServer, self.generateError(message: error?.localizedDescription ?? "Server error", errorType: .MCTileServerParseError)))
return
if parser.parse() {
print("have \(self.layers.count) layers")

for layer in self.layers {
print("Title: \(layer.title)")
print("Name: \(layer.name)")
print("CRS: \(layer.crs)")
print("Format: \(layer.format)\n\n")
}

let parser = XMLParser(data: data)
parser.delegate = self
tileServer.serverType = .wms
tileServer.url = (builtURL?.string)!
tileServer.layers = self.layers
self.layers = []

if parser.parse() {
print("have \(self.layers.count) layers")

for layer in self.layers {
print("Title: \(layer.title)")
print("Name: \(layer.name)")
print("CRS: \(layer.crs)")
print("Format: \(layer.format)\n\n")
}

tileServer.serverType = .wms
tileServer.url = (builtURL?.string)!
tileServer.layers = self.layers
self.layers = []

completion(MCTileServerResult.init(tileServer, self.generateError(message: "No error", errorType: MCServerErrorType.MCNoError)))
} else if (parser.parserError != nil) {
print("Parser error")
tileServer.serverType = .error
self.layers = []
let error:MCServerError = MCServerError.init(domain: "MCTileServerRepository", code: MCServerErrorType.MCURLInvalid.rawValue, userInfo: ["message" : "invalid URL"])
completion(MCTileServerResult.init(tileServer, error))
}
completion(MCTileServerResult.init(tileServer, self.generateError(message: "No error", errorType: MCServerErrorType.MCNoError)))
} else if (parser.parserError != nil) {
print("Parser error")
tileServer.serverType = .error
self.layers = []
let error:MCServerError = MCServerError.init(domain: "MCTileServerRepository", code: MCServerErrorType.MCURLInvalid.rawValue, userInfo: ["message" : "invalid URL"])
completion(MCTileServerResult.init(tileServer, error))
}
task.resume()
} else {
print("Invalid URL")
}
task.resume()
}


Expand Down
Loading

0 comments on commit 3b4bf00

Please sign in to comment.