Skip to content

Commit

Permalink
Merge branch 'master' into release
Browse files Browse the repository at this point in the history
  • Loading branch information
dg0yt committed Oct 21, 2018
2 parents 6916564 + 99c418c commit 3a3f4e4
Show file tree
Hide file tree
Showing 69 changed files with 3,057 additions and 2,601 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ endif()

# Project declaration

project(Mapper VERSION 0.8.2 LANGUAGES CXX C)
project(Mapper VERSION 0.8.3 LANGUAGES CXX C)

if(Mapper_VERSION_DISPLAY)
message(STATUS "Custom version display string: \"${Mapper_VERSION_DISPLAY}\"")
Expand Down
2 changes: 1 addition & 1 deletion android/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.8.2" android:versionCode="802" package="org.openorienteering.mapper" android:installLocation="auto">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.8.3" android:versionCode="803" package="org.openorienteering.mapper" android:installLocation="auto">
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="@string/long_app_name" android:icon="@drawable/icon">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|locale|fontScale|keyboard|keyboardHidden|navigation"
android:name="org.openorienteering.mapper.MapperActivity"
Expand Down
1 change: 1 addition & 0 deletions code-check-wrapper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ PATTERN=" \
file_import_export.cpp \
georeferencing_dialog.cpp \
gdal_manager.cpp \
gps_display.cpp \
key_button_bar.cpp \
/map.cpp \
map_editor.cpp \
Expand Down
21 changes: 20 additions & 1 deletion doc/manual/pages/android-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,28 @@ Note that the temporary trace is not saved in the map.
This removes the temporay traces and position markers. (They will also be discarded when closing the map file.)


#### ![ ](../mapper-images/pencil.png) Paint on template

By this tool, mapper supports free-hand drawing onto image templates. There is
a small selection of colors for drawing. White is used for corrections to
previous drawings. There is also a dedicated undo/redo feature.

This tool is an convenient alternative when you want to do only (or mostly)
drafting in the field, but draw the final version of the map at home on a PC.
It does not create new map objects but only alters the template you draw on.
This may help to deal with low processing power or battery runtime on mobile
devices.

Please note that direct drawing onto base map images is *not* recommended:
First, the eraser tool would also erase the base map. Second, these images
usually are in the lossy JPEG format which will introduce visible artifacts
when saving the file and loading it repeatedly.


#### ![ ](../mapper-images/paint-on-template-settings.png) Paint-on-template settings

This button allows to select the active image for scribbling (using the symbol above it).
This button allows to select an image template for scribbling,
or to add a new one covering the vicinity of your position.


-----
Expand Down
18 changes: 0 additions & 18 deletions doc/manual/pages/android-pc.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,3 @@ In this case, the easiest way is to first create a new map with the same symbol
After that, load the existing map as template in the new map. Then use the alignment tools for templates to move the existing map to match with the new georeferenced template. When you are finished, import the existing map template into the new map file using the corresponding action in the template dock widget, and you should be done.

Attention: especially for old maps, the whole existing map may be locally distorted. In this case it will not be possible to match the old map and the georeferenced template and the only way to georeference the map is to do a tedious undistortion. Mapper does not provide a tool for this.


## Preparing for free-hand scribbling

![ ](../mapper-images/pencil.png)

Mapper supports free-hand drawing onto image templates using the tool with the pencil icon shown above. This is especially convenient to use in case you want to do only (or mostly) drafting while you are in the field, and draw the final version of the map at home on a PC. It has the advantage of being quick and it only alters the template you draw on, i.e. it does not create new map objects, so Mapper's map display does not become slower. This may be relevant on mobile devices because of little processing power or because of battery runtime.

If you want to use this functionality, you should best load a separate, initially transparent image template in png format for it. Suited images can be downloaded here:

- [size 1024x1024](attachment/scribble_1024.png)
- [size 2048x2048](attachment/scribble_2048.png)

The images contain a red border, but are transparent everywhere else. After downloading a file, load it in your map file and move it so it covers the area you want to draw scribbles on. Make sure that the image resolution of the template is good enough by drawing a test scribble. If not, you need to scale it down using the template settings. You may also create multiple copies of the file and load them as separate templates.

Direct drawing onto base map images is NOT recommended because you will not be able to use the eraser without also erasing the base map and because these images usually are in the lossy JPEG format which will introduce visible artifacts when saving the file and loading it again.

Note that to view the scribbles on a PC after creating them on a mobile device, you need to transfer not only the map file, but also the affected image template file(s) back to the PC, as the scribbles are saved directly in the image files.
19 changes: 17 additions & 2 deletions doc/manual/pages/android-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,25 @@ OpenOrienteering Mapper for Android will create these folders when they are miss
You can transfer files from and to a PC via a USB cable. Android supports multiple file transfer protocols.

- MTP is the preferred method now. There is hardly any interference for apps while the device is connected to the PC.
Via MTP, Android will only show files which are known to its Media Scanner. If you cannot find a file such a recorded GPX track, a reboot of the device could trigger a rescan.
Via MTP, Android will only show files which are known to its Media Scanner.

- Mass Storage makes the storage unavailable for apps for the duration of the connection with the PC.
(Android also needs to terminate apps which are stored on the volume which is provided as mass storage.)
Unlike MTP, mass storage does not depend on the media scanner, so all files are always visible.

In some cases, users suffered from files being damaged during transfer. This can be worked around by choosing another method for file transfer. Remember to keep backups and to verify transferred files.
Note that after mapping, you might want to transfer back not only the modified map but also GPX tracks and templates you painted on.


## Data loss prevention and recovery

*Remember to keep backups and to verify transferred files.*

If a file appears to be corrupted after transfer back to PC, or you cannot find
a new file such as a recorded GPX track, a reboot of the Android device could
solve the issue. After the reboot, Android's media scanner will take notice of
new files and changed file sizes. However, Mapper v0.8.3 is expected to bring a
solution to this issue.

In some situations, the Mapper app might not be able to properly save data and
shutdown as quickly as requested by the Android operating system, for example
when you start other apps or when the device runs out of power.
Binary file modified doc/manual/pages/images/main_window.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
86 changes: 24 additions & 62 deletions src/core/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@

// IWYU pragma: no_forward_declare QRectF

#ifdef Q_OS_ANDROID
#include "core/storage_location.h"
#endif


namespace OpenOrienteering {

Expand Down Expand Up @@ -694,6 +698,15 @@ bool Map::exportTo(const QString& path, MapView* view, const FileFormat* format)
}

success = file.commit();
#ifdef Q_OS_ANDROID
if (success)
{
// Make the MediaScanner aware of the *updated* file. This is an
// attempt to resolve issues with files being transferred
// incompletely to the PC (#1115).
Android::mediaScannerScanFile(QFileInfo(path).absolutePath());
}
#endif
}

if (!success)
Expand Down Expand Up @@ -2239,96 +2252,45 @@ void Map::setCurrentPartIndex(std::size_t index)
}
}

std::size_t Map::reassignObjectsToMapPart(std::set<Object*>::const_iterator begin, std::set<Object*>::const_iterator end, std::size_t source, std::size_t destination)
{
Q_ASSERT(source < parts.size());
Q_ASSERT(destination < parts.size());

std::size_t count = 0;
MapPart* const source_part = parts[source];
MapPart* const target_part = parts[destination];
for (auto it = begin; it != end; ++it)
{
Object* const object = *it;
source_part->deleteObject(object, true);

int index = target_part->getNumObjects();
target_part->addObject(object, index);

++count;
}

setOtherDirty();

std::size_t const target_end = target_part->getNumObjects();
std::size_t const target_begin = target_end - count;

if (current_part_index == source)
{
int const selection_size = getNumSelectedObjects();

// When modifying the selection we must not use the original iterators
// because they may be operating on the selection and then become invalid!
for (std::size_t i = target_begin; i != target_end; ++i)
{
Object* const object = target_part->getObject(i);
if (isObjectSelected(object))
removeObjectFromSelection(object, false);
}

if (selection_size != getNumSelectedObjects())
emit objectSelectionChanged();
}

return target_begin;
}

std::size_t Map::reassignObjectsToMapPart(std::vector<int>::const_iterator begin, std::vector<int>::const_iterator end, std::size_t source, std::size_t destination)
int Map::reassignObjectsToMapPart(std::vector<int>::const_iterator first, std::vector<int>::const_iterator last, std::size_t source, std::size_t destination)
{
Q_ASSERT(source < parts.size());
Q_ASSERT(destination < parts.size());

bool selection_changed = false;

std::size_t count = 0;
MapPart* const source_part = parts[source];
MapPart* const target_part = parts[destination];
for (auto it = begin; it != end; ++it)
auto first_object = target_part->getNumObjects();
auto selection_size = getNumSelectedObjects();
for (auto it = first; it != last; ++it)
{
Q_ASSERT(*it < source_part->getNumObjects());
Object* const object = source_part->getObject(*it);

if (current_part_index == source && isObjectSelected(object))
{
removeObjectFromSelection(object, false);
selection_changed = true;
}

source_part->deleteObject(object, true);

int index = target_part->getNumObjects();
target_part->addObject(object, index);

++count;
target_part->addObject(object);
}

setOtherDirty();

if (selection_changed)
if (getNumSelectedObjects() != selection_size)
emit objectSelectionChanged();

return target_part->getNumObjects() - count;
return first_object;
}

std::size_t Map::mergeParts(std::size_t source, std::size_t destination)
int Map::mergeParts(std::size_t source, std::size_t destination)
{
Q_ASSERT(source < parts.size());
Q_ASSERT(destination < parts.size());

std::size_t count = 0;
int count = 0;
MapPart* const source_part = parts[source];
MapPart* const target_part = parts[destination];
// Preserve order (but not efficient)
for (std::size_t i = source_part->getNumObjects(); i > 0 ; --i)
for (auto i = source_part->getNumObjects(); i > 0 ; --i)
{
Object* object = source_part->getObject(0);
source_part->deleteObject(0, true);
Expand Down
18 changes: 6 additions & 12 deletions src/core/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -799,25 +799,19 @@ public slots:
*/
void setCurrentPartIndex(std::size_t index);

/**
* Moves all specified objects from the source to the destination map part.
*
* The objects will be continuously located at the end to the objects in the target part.
* Source object which were selected will be removed from the object selection.
*
* @return The index of the first object which has been reassigned.
*/
std::size_t reassignObjectsToMapPart(std::set<Object*>::const_iterator begin, std::set<Object*>::const_iterator end, std::size_t source, std::size_t destination);

/**
* Moves all specified objects from the source to the target map part.
*
* Objects are processed one by one. This means that processing one object
* changes the index of following objects. Thus the given indices must
* normally be in descending order.
*
* The objects will be continuously located at the end to the objects in the target part.
* Source object which were selected will be removed from the object selection.
*
* @return The index of the first object which has been reassigned.
*/
std::size_t reassignObjectsToMapPart(std::vector<int>::const_iterator begin, std::vector<int>::const_iterator end, std::size_t source, std::size_t destination);
int reassignObjectsToMapPart(std::vector<int>::const_iterator first, std::vector<int>::const_iterator last, std::size_t source, std::size_t destination);

/**
* Merges the source part with the destination part.
Expand All @@ -831,7 +825,7 @@ public slots:
*
* @return The index of the first object which has been reassigned.
*/
std::size_t mergeParts(std::size_t source, std::size_t destination);
int mergeParts(std::size_t source, std::size_t destination);


// Objects
Expand Down
16 changes: 9 additions & 7 deletions src/core/storage_location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,8 @@ namespace Android {
*/
static std::shared_ptr<const std::vector<StorageLocation>> locations_cache;

/**
* Tells the media scanner to register the given file or folder.
*
* This is required to make files quickly available for transfer via MTP.
*/
void mediaScannerScanFile(const QString path)

void mediaScannerScanFile(const QString& path)
{
static const auto ACTION_MEDIA_SCANNER_SCAN_FILE =
QAndroidJniObject::getStaticObjectField<jstring>("android/content/Intent",
Expand Down Expand Up @@ -285,7 +281,7 @@ QString StorageLocation::fileHintTextTemplate(Hint hint)
switch (hint)
{
case HintNormal:
return tr("'%1' is stored in a regular location.");
return {}; // No text for a regular location.

case HintApplication:
return tr("'%1' is located in app storage. The files will be removed when uninstalling the app.");
Expand All @@ -301,4 +297,10 @@ QString StorageLocation::fileHintTextTemplate(Hint hint)
}


QString OpenOrienteering::StorageLocation::hintText() const
{
return hint() == HintNormal ? QString{} : fileHintTextTemplate(hint()).arg(path());
}


} // namespace OpenOrienteering
30 changes: 22 additions & 8 deletions src/core/storage_location.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@

namespace OpenOrienteering {

namespace Android {

/**
* Tells the media scanner to register the given file or folder.
*
* This is required to make files quickly available for transfer via MTP.
*/
void mediaScannerScanFile(const QString& path);

}


// noexcept since Qt 5.5
constexpr bool qstring_is_nothrow_copy_constructible = std::is_nothrow_copy_constructible<QString>::value;
constexpr bool qstring_is_nothrow_move_constructible = std::is_nothrow_move_constructible<QString>::value;
Expand Down Expand Up @@ -65,13 +77,21 @@ class StorageLocation
/** Returns the path of this location. */
QString path() const;

/** Returns the hint for this location. */
/**
* Returns the hint for this location.
*
* This function returns an empty string for HintNormal.
*/
Hint hint() const;

/** Returns the text representing the hint for this location. */
QString hintText() const;

/** Returns a text template for giving the hint for the given path. */
/**
* Returns a text template for giving the hint for the given path.
*
* This function returns an empty string for HintNormal.
*/
static QString fileHintTextTemplate(Hint hint);


Expand Down Expand Up @@ -114,12 +134,6 @@ StorageLocation::Hint StorageLocation::hint() const
return m_hint;
}

inline
QString StorageLocation::hintText() const
{
return fileHintTextTemplate(hint()).arg(path());
}


} // namespace OpenOrienteering

Expand Down
6 changes: 2 additions & 4 deletions src/core/symbols/text_symbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -512,9 +512,9 @@ bool TextSymbol::equalsImpl(const Symbol* other, Qt::CaseSensitivity case_sensit
bold != text->bold ||
italic != text->italic ||
underline != text->underline ||
line_spacing != text->line_spacing ||
qAbs(line_spacing - text->line_spacing) > 0.0005f ||
paragraph_spacing != text->paragraph_spacing ||
character_spacing != text->character_spacing ||
qAbs(character_spacing - text->character_spacing) > 0.0005f ||
kerning != text->kerning ||
line_below != text->line_below ||
framing != text->framing)
Expand All @@ -536,8 +536,6 @@ bool TextSymbol::equalsImpl(const Symbol* other, Qt::CaseSensitivity case_sensit
line_below_distance != text->line_below_distance)
return false;
}
if (tab_interval != text->tab_interval)
return false;
if (custom_tabs.size() != text->custom_tabs.size())
return false;
for (size_t i = 0, end = custom_tabs.size(); i < end; ++i)
Expand Down
Loading

0 comments on commit 3a3f4e4

Please sign in to comment.