Skip to content

Commit

Permalink
version 1.8.4: support Interactive Map Layer - IML (experimental)
Browse files Browse the repository at this point in the history
Merge branch 'dev.iml' into master
ref: da63a13
  • Loading branch information
minff committed Jun 8, 2021
1 parent dcae220 commit 3f4bf89
Show file tree
Hide file tree
Showing 58 changed files with 2,293 additions and 788 deletions.
9 changes: 9 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
include:
- template: Security/Secret-Detection.gitlab-ci.yml
- template: Security/License-Scanning.gitlab-ci.yml
- template: Security/Dependency-Scanning.gitlab-ci.yml
- template: Security/SAST.gitlab-ci.yml

secret_detection:
variables:
GIT_DEPTH: 100
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Changelog

## Version 1.8.4 (2021-06-08)

#### New Features

* Supports HERE Platform Interactive Map Layers - IML (experimental)
* Enables loading, editing data in IML (experimental)

#### Bug Fixes

* Minor bug fixes

## Version 1.8.3 (2021-02-08)

#### Improvements
Expand Down
61 changes: 59 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,71 @@ Once you have installed and enabled the plugin XYZ Hub Connector in QGIS, it can

+ `Manage` : create new space, edit or delete existing space.

+ `Map Tile` : create HERE Map Tile layer given valid `app_id` and `app_code`.
+ `Map Tile` : create HERE Map Tile layer given valid `app_id` and `app_code`. Alternatively, `api_key` can also be used.

+ `Settings` :

+ `Clear cache` : empty the temporary cache folder. Active layers will be invalid after clearing cache.

When the user make some edits to the loaded layer, the changes can be pushed to XYZ Hub via the button `Push changes` in the toolbar.

### Configure Server connection

Official Data Hub server is predefined under name "HERE Server" and thus is not required to be created. The following steps are only required for self-hosted Data Hub server and HERE Platform server.

1. From the "Web" menu in QGIS, select "XYZ Hub Connector" > "Add HERE Layer".
2. Press the "Setup" button and then "Setup Server" to add a new server.
3. Click "Add" to add a new server.
4. Select server type

a. Server Type: DATAHUB, enter "HERE self-hosted Data Hub" as the name and your Data Hub URL as the server.

b. Server Type: PLATFORM, enter "HERE platform" as the name and PLATFORM_PRD as the server.

5. Click on OK to save the new server and OK again to return to the setup screen.

### Add HERE Data Hub Token

1. From the "Web" menu in QGIS, select "XYZ Hub Connector" > "Add HERE Layer".
2. Press the "Setup", ensure that "HERE Server" is selected in the Server drop down.
3. Click on "Add" to add your token.
4. Enter a name and corresponding Data Hub token created previously according to the guide https://www.here.xyz/api/getting-token/
5. Click on OK to save the token, and close the connection window

### Add HERE Platform Credentials

1. From the "Web" menu in QGIS, select "XYZ Hub Connector" > "Add HERE Layer".
2. Press the "Setup", ensure that "HERE Platform" is selected in the Server drop down.
3. Click on "Add" to add your credentials.
4. Enter "My credentials" as the name.
5. Select a credentials.properties containing your HERE Platform app credentials (typically location in `{USER_HOME}/.here/credentials.properties`
6. If you don't already have an app or a credentials.properties file then you can follow "platform credentials" section of this guide to create one: https://developer.here.com/documentation/java-scala-dev/dev_guide/topics/get-credentials.html
7. Grant access on the data to the HERE platform app so that it can access your project. Do so by following this guide: https://developer.here.com/documentation/identity-access-management/dev_guide/topics/manage-projects.html
8. Click on OK to save the credentials, and close the connection window

### Load Your Data from HERE Platform

1. Create a new project (Project → New), save the project
2. From the "Web" menu in QGIS, select "XYZ Hub Connector" > "Add HERE Layer"
3. From the Connection drop down, select the "HERE Platform" connection and the "My Credentials" credentials that you created previously
4. Click "Connect"
5. Select one or more Interactive Map Layer entries
6. Click on "Load" to load the data

**Note:** You can also add background map tiles via the "Map Tile" tab. You will need to use your credentials from https://developer.here.com/.

## Testing

Test with unittest
```
./runTest.sh -m unittest test
```

Test with pytest-xdist
```
./runTest.sh -m pytest -n 2 test
```

## Development

1. Clone this repository.
Expand All @@ -61,6 +118,6 @@ e.g. `sh makeBuild.sh 1.5.5`.
[CHANGELOG](CHANGELOG.md)
## License

Copyright (C) 2020 HERE Europe B.V.
Copyright (C) 2019-2021 HERE Europe B.V.

This project is licensed under the MIT license - see the [LICENSE](./LICENSE) file in the root of this project for license details.
101 changes: 55 additions & 46 deletions RELEASENOTE.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,55 @@
## Version 1.8.3 (2021-02-08)

⚡️ IMPROVEMENTS ⚡️
* Updates HERE Tiles service URL

🐛 FIXES 🐛
* Handles nested properties when uploading data
* Fixes compatibility with QGIS 3.10, 3.16

## Version 1.8.2 (2020-06-10)

✨ NEW FEATURES ✨
* Supports self-hosted XYZ Hub Server: token authentication, loading, uploading, editing data, managing spaces
* Supports Property query and selection (XYZ Hub API)
* Supports Api Key for HERE Tiles

⚡️ IMPROVEMENTS ⚡️
* UX improvement
* Improved layer organization

## Version 1.8.1 (2020-03-10)

⚡️ IMPROVEMENTS ⚡️
* Loading tile using Web Mercator projection

🐛 FIXES 🐛
* Fixed wrong data loaded from virtual space, cf. https://www.here.xyz/cli/cli/#virtual-spaces

## Version 1.8.0 (2020-02-12)

✨ NEW FEATURES ✨
* Introducing three loading modes:
* Live loading - interactive mode for visualization of dynamic dataset with full editing capabilities
* Incremental loading - interactive mode with caching for visualization and exploration of large dataset
* Static loading - mode for importing and analysis of static dataset

⚡️ IMPROVEMENTS ⚡️
* Improve interactive loading mode behaviors
* Resume loading after open saved project or network interruption
* Save loader params into project
* Generate unique layer name

🐛 FIXES 🐛
* Fix errors when delete layers or close project
* Fix errors when opening project
* Fix progress bar behavior
## Version 1.8.4 (2021-06-08)

✨ NEW FEATURES ✨
* Supports HERE Platform Interactive Map Layers - IML (experimental)
* Enables loading, editing data in IML (experimental)

🐛 FIXES 🐛
* Minor bug fixes

## Version 1.8.3 (2021-02-08)

⚡️ IMPROVEMENTS ⚡️
* Updates HERE Tiles service URL

🐛 FIXES 🐛
* Handles nested properties when uploading data
* Fixes compatibility with QGIS 3.10, 3.16

## Version 1.8.2 (2020-06-10)

✨ NEW FEATURES ✨
* Supports self-hosted XYZ Hub Server: token authentication, loading, uploading, editing data, managing spaces
* Supports Property query and selection (XYZ Hub API)
* Supports Api Key for HERE Tiles

⚡️ IMPROVEMENTS ⚡️
* UX improvement
* Improved layer organization

## Version 1.8.1 (2020-03-10)

⚡️ IMPROVEMENTS ⚡️
* Loading tile using Web Mercator projection

🐛 FIXES 🐛
* Fixed wrong data loaded from virtual space, cf. https://www.here.xyz/cli/cli/#virtual-spaces

## Version 1.8.0 (2020-02-12)

✨ NEW FEATURES ✨
* Introducing three loading modes:
* Live loading - interactive mode for visualization of dynamic dataset with full editing capabilities
* Incremental loading - interactive mode with caching for visualization and exploration of large dataset
* Static loading - mode for importing and analysis of static dataset

⚡️ IMPROVEMENTS ⚡️
* Improve interactive loading mode behaviors
* Resume loading after open saved project or network interruption
* Save loader params into project
* Generate unique layer name

🐛 FIXES 🐛
* Fix errors when delete layers or close project
* Fix errors when opening project
* Fix progress bar behavior
4 changes: 3 additions & 1 deletion XYZHubConnector/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
__copyright__ = "Copyright 2019, HERE Europe B.V."

__license__ = "MIT"
__version__ = "1.8.3"
__version__ = "1.8.4"
__maintainer__ = "Minh Nguyen"
__email__ = "[email protected]"
__status__ = "Development"

def classFactory(iface):
"""invoke plugin"""
from . import config
config.load_external_lib()
from .plugin import XYZHubConnector
return XYZHubConnector(iface)
10 changes: 10 additions & 0 deletions XYZHubConnector/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
###############################################################################

import os
import sys

from qgis.core import QgsApplication

Expand All @@ -24,7 +25,16 @@
USER_PLUGIN_DIR = os.path.join(USER_DIR, PLUGIN_NAME)
TMP_DIR = os.path.join(USER_DIR, PLUGIN_NAME, "tmp")
LOG_FILE = os.path.join(USER_DIR, PLUGIN_NAME, "qgis.log")
EXTERNAL_LIB_DIR = os.path.join(PLUGIN_DIR, "external")

os.makedirs(TMP_DIR,exist_ok=True)

override_config(dict(filter(lambda kv: kv[0].isupper(), locals().items())))

def load_external_lib():
if EXTERNAL_LIB_DIR not in sys.path:
sys.path.insert(0, EXTERNAL_LIB_DIR)

def unload_external_lib():
if EXTERNAL_LIB_DIR in sys.path:
sys.path.remove(EXTERNAL_LIB_DIR)
54 changes: 30 additions & 24 deletions XYZHubConnector/gui/base_token_dialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@

TokenUI = get_ui_class('token_dialog.ui')


class BaseTokenDialog(QDialog, TokenUI):
title = "Setup XYZ Hub Token"
title = "Setup HERE Token"
message = ""
token_info_keys = ["name", "token"]
NewInfoDialog = NewTokenInfoDialog
EditInfoDialog = EditTokenInfoDialog

def __init__(self, parent=None):
"""init window"""
QDialog.__init__(self, parent)
Expand All @@ -41,7 +42,7 @@ def set_server(self, server):
self.token_model.set_server(server)

def config(self, token_model: TokenModel):
self._config( token_model)
self._config(token_model)
self.tableView.setSelectionMode(self.tableView.SingleSelection)
self.tableView.setSelectionBehavior(self.tableView.SelectRows)
self.tableView.setEditTriggers(self.tableView.NoEditTriggers)
Expand All @@ -50,18 +51,18 @@ def config(self, token_model: TokenModel):
# dont use pressed, activated
self.tableView.selectionModel().currentChanged.connect(self.ui_enable_btn)

self.btn_add.clicked.connect( self.ui_add_token)
self.btn_edit.clicked.connect( self.ui_edit_token)
self.btn_delete.clicked.connect( self.ui_delete_token)
self.btn_up.clicked.connect( self.ui_move_token_up)
self.btn_down.clicked.connect( self.ui_move_token_down)
self.btn_add.clicked.connect(self.ui_add_token)
self.btn_edit.clicked.connect(self.ui_edit_token)
self.btn_delete.clicked.connect(self.ui_delete_token)
self.btn_up.clicked.connect(self.ui_move_token_up)
self.btn_down.clicked.connect(self.ui_move_token_down)

def _config(self, token_model: TokenModel):
self.token_model = token_model
self.tableView.setModel( token_model)
self.accepted.connect( token_model.submit_cache)
self.rejected.connect( token_model.refresh_model)
self.tableView.setModel(token_model)
self.accepted.connect(token_model.submit_cache)
self.rejected.connect(token_model.refresh_model)

def exec_(self):
# self.tableView.resizeColumnsToContents()
# self.tableView.clearFocus()
Expand All @@ -72,14 +73,19 @@ def exec_(self):
idx = self.tableView.currentIndex().row()
if idx >= 0: self.set_active_idx(idx)
return ret
def set_active_idx(self,idx):

def set_active_idx(self, idx):
self._active_idx = idx

def get_active_idx(self):
return self._active_idx

def set_active_server_idx(self, idx):
self._active_server_idx = idx

def get_active_server_idx(self):
return self._active_server_idx

def ui_enable_btn(self, *a):
index = self.tableView.currentIndex()
flag = index.isValid()
Expand All @@ -90,7 +96,7 @@ def ui_enable_btn(self, *a):
self.btn_down,
]:
btn.setEnabled(flag)

if self.token_model.is_protected_data(index.row()):
for btn in [
self.btn_edit,
Expand All @@ -103,16 +109,16 @@ def _get_current_token_info(self):
return self.token_model.get_data(row)

def _make_delete_message(self, token_info):
token_msg = ", ".join("%s: %s"%it for it in token_info.items())
return "Do you want to Delete token (%s)?"%token_msg
token_msg = ", ".join("%s: %s" % it for it in token_info.items())
return "Do you want to Delete token (%s)?" % token_msg

def ui_add_token(self):
dialog = self.NewInfoDialog(self)
ret = dialog.exec_()
if ret != dialog.Accepted: return

self._add_token(dialog.get_info())
self.tableView.selectRow(self.token_model.rowCount()-1)
self.tableView.selectRow(self.token_model.rowCount() - 1)

def ui_edit_token(self):
dialog = self.EditInfoDialog(self)
Expand All @@ -138,8 +144,8 @@ def ui_move_token_up(self):
it = self.token_model.takeRow(row)
self.modify_token_idx(row)

row = max(row-1,0)
self.token_model.insertRow(max(row,0), it)
row = max(row - 1, 0)
self.token_model.insertRow(max(row, 0), it)
self.tableView.selectRow(row)
self.modify_token_idx(row)

Expand All @@ -148,7 +154,7 @@ def ui_move_token_down(self):
it = self.token_model.takeRow(row)
self.modify_token_idx(row)

row = min(row+1, self.token_model.rowCount())
row = min(row + 1, self.token_model.rowCount())
self.token_model.insertRow(row, it)
self.tableView.selectRow(row)
self.modify_token_idx(row)
Expand All @@ -158,15 +164,15 @@ def _add_token(self, token_info: dict):
QStandardItem(token_info[k])
for k in self.token_info_keys
])

def _edit_token(self, token_info: dict):
row = self.tableView.currentIndex().row()
self.token_model.insertRow(row+1, [
self.token_model.insertRow(row + 1, [
QStandardItem(token_info[k])
for k in self.token_info_keys
])
it = self.token_model.takeRow(row)
self.modify_token_idx(row)

def modify_token_idx(self, idx):
self.token_model.modify_token_idx(idx)
Loading

0 comments on commit 3f4bf89

Please sign in to comment.