summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
Diffstat (limited to 'android')
-rw-r--r--android/.gitignore1
-rw-r--r--android/Bootstrap/Makefile.shared25
-rw-r--r--android/Bootstrap/src/org/libreoffice/kit/Document.java1
-rw-r--r--android/Bootstrap/src/org/libreoffice/kit/LibreOfficeKit.java1
-rw-r--r--android/Makefile6
-rw-r--r--android/README.md (renamed from android/README)224
-rw-r--r--android/default-document/example.odtbin297986 -> 277168 bytes
-rw-r--r--android/default-document/example_test.odsbin0 -> 7697 bytes
-rw-r--r--android/source/AndroidManifest.xml37
-rw-r--r--android/source/Makefile11
-rw-r--r--android/source/build.gradle105
-rw-r--r--android/source/gradle.properties3
-rw-r--r--android/source/gradle/wrapper/gradle-wrapper.jarbin49896 -> 63375 bytes
-rw-r--r--android/source/gradle/wrapper/gradle-wrapper.properties5
-rwxr-xr-xandroid/source/gradlew310
-rwxr-xr-xandroid/source/gradlew.bat66
-rw-r--r--android/source/ic_launcher-web.pngbin23194 -> 26399 bytes
-rw-r--r--android/source/lint-baseline.xml2341
-rw-r--r--android/source/lint.xml9
-rw-r--r--android/source/res/drawable-hdpi/action_search.pngbin1759 -> 0 bytes
-rw-r--r--android/source/res/drawable-hdpi/action_search_light.pngbin1764 -> 0 bytes
-rw-r--r--android/source/res/drawable-hdpi/ic_folder_48dp.xml5
-rw-r--r--android/source/res/drawable-hdpi/ic_keyboard.xml4
-rw-r--r--android/source/res/drawable-hdpi/lo_icon.pngbin1950 -> 0 bytes
-rw-r--r--android/source/res/drawable-mdpi/lo_icon.pngbin1180 -> 0 bytes
-rw-r--r--android/source/res/drawable-xxxhdpi/decrementindent.pngbin0 -> 962 bytes
-rw-r--r--android/source/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png (renamed from android/source/res/drawable-xxxhdpi/ic_keyboard_black_24dp.png)bin301 -> 301 bytes
-rw-r--r--android/source/res/drawable-xxxhdpi/incrementindent.pngbin0 -> 912 bytes
-rw-r--r--android/source/res/drawable/calc.pngbin14818 -> 13611 bytes
-rw-r--r--android/source/res/drawable/draw.pngbin18445 -> 17013 bytes
-rw-r--r--android/source/res/drawable/ic_add_24dp.xml (renamed from android/source/res/drawable/ic_add_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_arrow_back_24dp.xml (renamed from android/source/res/drawable/ic_arrow_back_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_auto_color.xml10
-rw-r--r--android/source/res/drawable/ic_cloud_black_24dp.xml9
-rw-r--r--android/source/res/drawable/ic_content_copy_24dp.xml (renamed from android/source/res/drawable/ic_content_copy_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_content_cut_24dp.xml (renamed from android/source/res/drawable/ic_content_cut_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_content_paste_24dp.xml (renamed from android/source/res/drawable/ic_content_paste_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_decrementindent.xml3
-rw-r--r--android/source/res/drawable/ic_filter_list_24dp.xml (renamed from android/source/res/drawable/ic_filter_list_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_folder_24dp.xml (renamed from android/source/res/drawable/ic_folder_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_format_clear_24dp.xml (renamed from android/source/res/drawable/ic_format_clear_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_grid_off_24dp.xml (renamed from android/source/res/drawable/ic_grid_off_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_grid_on_24dp.xml (renamed from android/source/res/drawable/ic_grid_on_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_incrementindent.xml3
-rw-r--r--android/source/res/drawable/ic_insert_drive_file_black_24dp.xml7
-rw-r--r--android/source/res/drawable/ic_keyboard_backspace_black_24dp.xml9
-rw-r--r--android/source/res/drawable/ic_line.xml2
-rw-r--r--android/source/res/drawable/ic_menu_back.pngbin1900 -> 0 bytes
-rw-r--r--android/source/res/drawable/ic_rect.xml2
-rw-r--r--android/source/res/drawable/ic_sd_card_black_24dp.xml9
-rw-r--r--android/source/res/drawable/ic_settings_24dp.xml (renamed from android/source/res/drawable/ic_settings_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_sort_24dp.xml (renamed from android/source/res/drawable/ic_sort_black_24dp.xml)2
-rw-r--r--android/source/res/drawable/ic_storage_black_24dp.xml9
-rw-r--r--android/source/res/drawable/ic_usb_black_24dp.xml7
-rw-r--r--android/source/res/drawable/impress.pngbin13936 -> 15005 bytes
-rw-r--r--android/source/res/drawable/label_background.xml4
-rw-r--r--android/source/res/drawable/writer.pngbin15878 -> 15781 bytes
-rw-r--r--android/source/res/layout/about.xml11
-rw-r--r--android/source/res/layout/activity_directory_browser.xml6
-rw-r--r--android/source/res/layout/activity_document_browser.xml95
-rw-r--r--android/source/res/layout/activity_main.xml28
-rw-r--r--android/source/res/layout/file_explorer_grid_item.xml42
-rw-r--r--android/source/res/layout/file_grid.xml25
-rw-r--r--android/source/res/layout/file_list.xml20
-rw-r--r--android/source/res/layout/file_list_item.xml58
-rw-r--r--android/source/res/layout/fragment_directory_browser.xml71
-rw-r--r--android/source/res/layout/item_recent_files.xml1
-rw-r--r--android/source/res/layout/number_picker.xml4
-rw-r--r--android/source/res/layout/toolbar_bottom.xml47
-rw-r--r--android/source/res/layout/toolbar_color_picker.xml46
-rw-r--r--android/source/res/menu/context_menu.xml7
-rw-r--r--android/source/res/menu/main.xml28
-rw-r--r--android/source/res/menu/navigation_menu.xml35
-rw-r--r--android/source/res/menu/view_menu.xml54
-rw-r--r--android/source/res/mipmap-hdpi/ic_launcher.pngbin1529 -> 6202 bytes
-rw-r--r--android/source/res/mipmap-mdpi/ic_launcher.pngbin950 -> 1310 bytes
-rw-r--r--android/source/res/mipmap-xhdpi/ic_launcher.pngbin2158 -> 7033 bytes
-rw-r--r--android/source/res/mipmap-xxhdpi/ic_launcher.pngbin5007 -> 8868 bytes
-rw-r--r--android/source/res/mipmap-xxxhdpi/ic_launcher.pngbin7896 -> 11149 bytes
-rw-r--r--android/source/res/values-ab/strings.xml2
-rw-r--r--android/source/res/values-ast/strings.xml121
-rw-r--r--android/source/res/values-ca/strings.xml121
-rw-r--r--android/source/res/values-cs/strings.xml121
-rw-r--r--android/source/res/values-cy/strings.xml121
-rw-r--r--android/source/res/values-de/strings.xml128
-rw-r--r--android/source/res/values-dsb/strings.xml121
-rw-r--r--android/source/res/values-el/strings.xml121
-rw-r--r--android/source/res/values-es/strings.xml121
-rw-r--r--android/source/res/values-eu/strings.xml121
-rw-r--r--android/source/res/values-fa/strings.xml121
-rw-r--r--android/source/res/values-fi/strings.xml2
-rw-r--r--android/source/res/values-fr/strings.xml121
-rw-r--r--android/source/res/values-gl/strings.xml121
-rw-r--r--android/source/res/values-hsb/strings.xml121
-rw-r--r--android/source/res/values-hu/strings.xml121
-rw-r--r--android/source/res/values-hy/strings.xml121
-rw-r--r--android/source/res/values-ia/strings.xml78
-rw-r--r--android/source/res/values-in/strings.xml91
-rw-r--r--android/source/res/values-is/strings.xml121
-rw-r--r--android/source/res/values-it/strings.xml121
-rw-r--r--android/source/res/values-ja/strings.xml2
-rw-r--r--android/source/res/values-kk/strings.xml2
-rw-r--r--android/source/res/values-ne/strings.xml23
-rw-r--r--android/source/res/values-night/colors.xml6
-rw-r--r--android/source/res/values-nl/strings.xml121
-rw-r--r--android/source/res/values-pa/strings.xml118
-rw-r--r--android/source/res/values-pl/strings.xml121
-rw-r--r--android/source/res/values-pt-rBR/strings.xml121
-rw-r--r--android/source/res/values-pt/strings.xml121
-rw-r--r--android/source/res/values-sk/strings.xml22
-rw-r--r--android/source/res/values-sl/strings.xml121
-rw-r--r--android/source/res/values-tr/strings.xml128
-rw-r--r--android/source/res/values-uk/strings.xml121
-rw-r--r--android/source/res/values-zh-rTW/strings.xml121
-rw-r--r--android/source/res/values/arrays.xml47
-rw-r--r--android/source/res/values/colors.xml6
-rw-r--r--android/source/res/values/dimens.xml1
-rw-r--r--android/source/res/values/integers.xml6
-rw-r--r--android/source/res/values/strings.xml113
-rw-r--r--android/source/res/values/themes.xml7
-rw-r--r--android/source/res/xml/documentprovider_preferences.xml38
-rw-r--r--android/source/res/xml/libreoffice_preferences.xml31
-rw-r--r--android/source/src/java/org/libreoffice/AboutDialogFragment.java67
-rw-r--r--android/source/src/java/org/libreoffice/ColorPaletteAdapter.java20
-rw-r--r--android/source/src/java/org/libreoffice/ColorPickerAdapter.java86
-rw-r--r--android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java1
-rw-r--r--android/source/src/java/org/libreoffice/FontController.java91
-rw-r--r--android/source/src/java/org/libreoffice/FormattingController.java153
-rw-r--r--android/source/src/java/org/libreoffice/InvalidationHandler.java66
-rw-r--r--android/source/src/java/org/libreoffice/LOEvent.java9
-rw-r--r--android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java2
-rw-r--r--android/source/src/java/org/libreoffice/LOKitShell.java12
-rw-r--r--android/source/src/java/org/libreoffice/LOKitThread.java106
-rw-r--r--android/source/src/java/org/libreoffice/LOKitTileProvider.java217
-rw-r--r--android/source/src/java/org/libreoffice/LibreOfficeApplication.java4
-rw-r--r--android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java517
-rw-r--r--android/source/src/java/org/libreoffice/LocaleHelper.java3
-rw-r--r--android/source/src/java/org/libreoffice/PasswordDialogFragment.java6
-rw-r--r--android/source/src/java/org/libreoffice/PresentationActivity.java27
-rw-r--r--android/source/src/java/org/libreoffice/SearchController.java13
-rw-r--r--android/source/src/java/org/libreoffice/ThumbnailCreator.java2
-rw-r--r--android/source/src/java/org/libreoffice/TileProvider.java24
-rw-r--r--android/source/src/java/org/libreoffice/ToolbarController.java174
-rw-r--r--android/source/src/java/org/libreoffice/UNOCommandsController.java8
-rw-r--r--android/source/src/java/org/libreoffice/canvas/BitmapHandle.java2
-rw-r--r--android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java38
-rw-r--r--android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java2
-rw-r--r--android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java18
-rw-r--r--android/source/src/java/org/libreoffice/storage/DocumentProviderFactory.java128
-rw-r--r--android/source/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java102
-rw-r--r--android/source/src/java/org/libreoffice/storage/IDocumentProvider.java70
-rw-r--r--android/source/src/java/org/libreoffice/storage/IFile.java116
-rw-r--r--android/source/src/java/org/libreoffice/storage/IOUtils.java56
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/BrowserSelectorActivity.java153
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserActivity.java42
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserFragment.java199
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/ExternalFile.java163
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/ExtsdDocumentsProvider.java175
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/IExternalDocumentProvider.java22
-rw-r--r--android/source/src/java/org/libreoffice/storage/external/OTGDocumentsProvider.java90
-rw-r--r--android/source/src/java/org/libreoffice/storage/local/LocalDocumentsDirectoryProvider.java73
-rw-r--r--android/source/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java60
-rw-r--r--android/source/src/java/org/libreoffice/storage/local/LocalFile.java103
-rw-r--r--android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java178
-rw-r--r--android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java192
-rw-r--r--android/source/src/java/org/libreoffice/ui/FileUtilities.java206
-rw-r--r--android/source/src/java/org/libreoffice/ui/FolderIconView.java204
-rw-r--r--android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java1139
-rw-r--r--android/source/src/java/org/libreoffice/ui/PageView.java18
-rw-r--r--android/source/src/java/org/libreoffice/ui/RecentFile.java25
-rw-r--r--android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java18
-rw-r--r--android/source/src/java/org/mozilla/gecko/ZoomConstraints.java14
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/GLController.java78
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java16
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java34
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java83
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/LayerView.java128
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java4
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java9
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java2
-rw-r--r--android/source/src/java/org/mozilla/gecko/gfx/SubTile.java14
181 files changed, 7331 insertions, 5715 deletions
diff --git a/android/.gitignore b/android/.gitignore
index 163145dd63fa..de608fea3c14 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -6,6 +6,7 @@
/source/build/
/source/captures/
/source/jni/Application.mk
+/source/res_generated
/jniLibs/
/source/liboSettings.gradle
/source/local.properties
diff --git a/android/Bootstrap/Makefile.shared b/android/Bootstrap/Makefile.shared
index f40693615f0a..0cd5ec6fcbda 100644
--- a/android/Bootstrap/Makefile.shared
+++ b/android/Bootstrap/Makefile.shared
@@ -23,7 +23,7 @@ OBJLOCAL=$(BUILDDIR)/android/obj/local/$(ANDROID_APP_ABI)
#
local.properties: $(BUILDDIR)/config_host.mk
- echo sdk.dir=$(ANDROID_SDK_HOME) >local.properties
+ echo sdk.dir=$(ANDROID_SDK_DIR) >local.properties
#
# Build / link the single .so for this app
@@ -60,18 +60,18 @@ WHOLELIBS = \
$(OBJLOCAL)/liblo-native-code.so : native-code.cxx $(ALL_STATIC_LIBS)
@echo "Linking $@"
mkdir -p $(OBJLOCAL)
- $(CXX) -fuse-ld=gold -Wl,--build-id=sha1 -Wl,--gc-sections -Wl,--version-script=../Bootstrap/version.map -Wl,--no-keep-files-mapped -Wl,--no-undefined -DANDROID -DDISABLE_DYNLOADING -shared -Wl,-soname,liblo-native-code.so -o $(OBJLOCAL)/liblo-native-code.so -I$(BUILDDIR)/config_host -I$(SRCDIR)/include native-code.cxx -L$(INSTDIR)/$(LIBO_LIB_FOLDER) $(WHOLELIBS) $(LIBS) -lc++_static -lc++abi $(if $(filter-out arm64-v8a x86_64,$(ANDROID_APP_ABI)),-landroid_support) $(if $(filter armeabi-v7a,$(ANDROID_APP_ABI)),-lunwind) $(addprefix -l,$(NSSLIBS)) -lGLESv2 -landroid -ljnigraphics -llog -lz
+ $(CXX) -Wl,--build-id=sha1 -Wl,--gc-sections -Wl,--version-script=../Bootstrap/version.map -Wl,--no-undefined -DANDROID -DDISABLE_DYNLOADING -shared -Wl,-soname,liblo-native-code.so -o $(OBJLOCAL)/liblo-native-code.so -I$(BUILDDIR)/config_host -I$(SRCDIR)/include native-code.cxx -L$(INSTDIR)/$(LIBO_LIB_FOLDER) $(WHOLELIBS) $(LIBS) -lc++_static -lc++abi $(if $(filter-out arm64-v8a x86_64,$(ANDROID_APP_ABI)),-landroid_support) $(if $(filter armeabi-v7a,$(ANDROID_APP_ABI)),-lunwind) $(addprefix -l,$(NSSLIBS)) -lGLESv2 -landroid -ljnigraphics -llog -lz
$(SODEST)/liblo-native-code.so : $(OBJLOCAL)/liblo-native-code.so
mkdir -p $(SODEST)
$(STRIP) -o $(SODEST)/liblo-native-code.so $(OBJLOCAL)/liblo-native-code.so
#to keep some symbols, eg.: $(STRIP) -o $(SODEST)/liblo-native-code.so $(OBJLOCAL)/liblo-native-code.so -w -K 'Java*'
-$(SODEST)/nss-libraries :
+$(SODEST)/nss-libraries :
mkdir -p $(SODEST)
$(foreach lib,$(NSSLIBS),$(STRIP) -o $(SODEST)/lib$(lib).so $(INSTDIR)/$(LIBO_LIB_FOLDER)/lib$(lib).so;)
-$(SODEST)/libc++_shared.so : $(ANDROID_NDK_HOME)/sources/cxx-stl/llvm-libc++/libs/$(ANDROID_APP_ABI)/libc++_shared.so
+$(SODEST)/libc++_shared.so : $(ANDROID_TOOLCHAIN)/sysroot/usr/lib/$(ANDROID_SYSROOT_PLATFORM)/libc++_shared.so
mkdir -p $(SODEST)
cp $< $@
@@ -83,10 +83,12 @@ link-so: $(SODEST)/liblo-native-code.so $(SODEST)/nss-libraries $(SODEST)/libc++
# can't "stop" a device anyway.)
stop-start-cycle:
- $(ANDROID_SDK_HOME)/platform-tools/adb shell stop && $(ANDROID_SDK_HOME)/platform-tools/adb shell start && sleep 10
+ $(ANDROID_SDK_DIR)/platform-tools/adb shell stop && $(ANDROID_SDK_DIR)/platform-tools/adb shell start && sleep 10
# build-host specific stuff (build paths and the like) to keep build.gradle static
-liboSettings.gradle: $(BUILDDIR)/config_build.mk $(BUILDDIR)/config_host.mk
+liboSettings.gradle: $(BUILDDIR)/config_build.mk $(BUILDDIR)/config_host.mk \
+ $(wildcard $(INSTDIR)/program/version.ini $(INSTDIR)/program/versionrc) \
+ $(SRCDIR)/android/Bootstrap/Makefile.shared
@echo "creating $@"
( \
echo "// created by Makefile.shared - your changes will be overridden" \
@@ -100,14 +102,21 @@ liboSettings.gradle: $(BUILDDIR)/config_build.mk $(BUILDDIR)/config_host.mk
&& echo " liboSharedResFolder = '$(LIBO_SHARE_RESOURCE_FOLDER)'" \
&& echo " liboUREJavaFolder = '$(LIBO_URE_SHARE_JAVA_FOLDER)'" \
&& echo " liboShareJavaFolder = '$(LIBO_SHARE_JAVA_FOLDER)'" \
- && echo " liboExampleDocument = '$(if $(exampleDocument),$(exampleDocument),$(SRC_ROOT)/android/default-document/example.odt)'" \
&& echo " liboVersionMajor = '$(LIBO_VERSION_MAJOR)'" \
&& echo " liboVersionMinor = '$(LIBO_VERSION_MINOR)'" \
&& echo " liboGitFullCommit = '$(shell cd $(SRCDIR) && git log -1 --format=%H)'" \
&& echo "}" \
+ && echo "android {" \
+ && echo " ndkPath '$(ANDROID_NDK_DIR)'" \
+ && echo "}" \
&& echo "android.defaultConfig {" \
&& echo " applicationId '$(ANDROID_PACKAGE_NAME)'" \
+ && echo " archivesBaseName = 'LibreOfficeViewer'" \
+ && echo " minSdkVersion = $(ANDROID_API_LEVEL)" \
&& echo " versionCode project.hasProperty('cmdVersionCode') ? cmdVersionCode.toInteger() : $(if $(versionCode),$(versionCode),1)" \
- && echo " versionName '$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)$(LIBO_VERSION_SUFFIX)$(LIBO_VERSION_SUFFIX_SUFFIX)/$(shell cd $(SRCDIR) && git log -1 --format=%h)/$(OOO_VENDOR)'" \
+ && echo " versionName '$(LIBO_VERSION_MAJOR).$(LIBO_VERSION_MINOR).$(LIBO_VERSION_MICRO).$(LIBO_VERSION_PATCH)$(LIBO_VERSION_SUFFIX)$(LIBO_VERSION_SUFFIX_SUFFIX)'" \
+ && echo " buildConfigField('String', 'BUILD_ID_SHORT', '\"$(shell cd $(SRCDIR) && git log -1 --format=%h)\"')" \
+ && echo " buildConfigField('String', 'VENDOR', '\"$(OOO_VENDOR)\"')" \
+ && echo " buildConfigField('String', 'PRIVACY_POLICY_URL', '\"$(PRIVACY_POLICY_URL)\"')" \
&& echo "}" \
) > $@
diff --git a/android/Bootstrap/src/org/libreoffice/kit/Document.java b/android/Bootstrap/src/org/libreoffice/kit/Document.java
index 69f8f76c3eb4..7d95268e224f 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/Document.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/Document.java
@@ -92,6 +92,7 @@ public class Document {
public static final int CALLBACK_COMMENT = 32;
public static final int CALLBACK_INVALIDATE_HEADER = 33;
public static final int CALLBACK_CELL_ADDRESS = 34;
+ public static final int CALLBACK_SC_FOLLOW_JUMP = 54;
/**
* Set text selection types
diff --git a/android/Bootstrap/src/org/libreoffice/kit/LibreOfficeKit.java b/android/Bootstrap/src/org/libreoffice/kit/LibreOfficeKit.java
index f6658d64806a..f7597c29a86c 100644
--- a/android/Bootstrap/src/org/libreoffice/kit/LibreOfficeKit.java
+++ b/android/Bootstrap/src/org/libreoffice/kit/LibreOfficeKit.java
@@ -102,6 +102,7 @@ class NativeLibLoader {
System.loadLibrary("smime3");
System.loadLibrary("ssl3");
+ System.loadLibrary("c++_shared");
System.loadLibrary("lo-native-code");
done = true;
}
diff --git a/android/Makefile b/android/Makefile
index 288932bbe1b6..a0a7231f7b07 100644
--- a/android/Makefile
+++ b/android/Makefile
@@ -13,10 +13,10 @@ include $(module_directory)/../solenv/gbuild/partial_build.mk
.PHONY: sign
SIGNED_APK := $(BUILDDIR)/android/source/bin/LibreOfficeViewer.apk
-RELEASE_APK_USAGE := echo; echo "Usage: make versionCode=<version_num+1> exampleDocument=</absolute/path/example.odt> key=<key_name> release-apk"
+RELEASE_APK_USAGE := echo; echo "Usage: make versionCode=<version_num+1> key=<key_name> release-apk"
release-apk: build
- # versionCode and key are mandatory, exampleDocument is not
+ # versionCode and key are mandatory
@if test -z "$(versionCode)" ; then $(RELEASE_APK_USAGE) ; exit 1 ; fi
@if test -z "$(key)" ; then $(RELEASE_APK_USAGE) ; exit 1 ; fi
@@ -24,7 +24,7 @@ release-apk: build
# the actual signing
jarsigner --verbose -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ~/.keystore $(BUILDDIR)/android/source/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(key)
- $(ANDROID_SDK_HOME)/build-tools/*/zipalign -v 4 $(BUILDDIR)/android/source/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(SIGNED_APK)
+ $(ANDROID_SDK_DIR)/build-tools/*/zipalign -v 4 $(BUILDDIR)/android/source/build/outputs/apk/LibreOfficeViewer-strippedUI-release-unsigned.apk $(SIGNED_APK)
@echo
@echo "Resulting signed apk: $(SIGNED_APK)"
diff --git a/android/README b/android/README.md
index 5b27ceb8e971..919122df38d1 100644
--- a/android/README
+++ b/android/README.md
@@ -1,128 +1,118 @@
-LibreOffice Android
-*******************
+# LibreOffice for Android
-Bootstrap
-*********
+## Bootstrap
Contains common code for all projects on Android to bootstrap LibreOffice. In
-addition it is a home to LibreOfficeKit (LOK - see libreofficekit/README) JNI
+addition it is a home to `LibreOfficeKit` (LOK - see `libreofficekit/README.md`) JNI
classes.
-stuff in source directory
-*************************
+## Stuff in Source Directory
LibreOffice Android application - the code is based on Fennec (Firefox for Android).
It uses OpenGL ES 2 for rendering of the document tiles which are gathered from
LibreOffice using LOK. The application contains the LibreOffice core in one shared
-library: liblo-native-code.so, which is bundled together with the application.
+library: `liblo-native-code.so`, which is bundled together with the application.
-Architecture and Threading
-**************************
+## Architecture and Threading
The application implements editing support using 4 threads:
+
1. The Android UI thread, we can't perform anything here that would take a considerable
amount of time.
2. An OpenGL thread which contains the OpenGL context and is responsible for drawing
all layers (including tiles) to the screen.
-3. A thread (LOKitThread), that performs LibreOfficeKit calls, which may take more time
+3. A thread (`LOKitThread`), that performs `LibreOfficeKit` calls, which may take more time
to complete. In addition it also receives events from the soffice thread (see below)
when the callback emits an event. Events are stored in a blocking queue (thread
processes events in FCFS order, goes to sleep when no more event is available and
awakens when there are events in the queue again).
4. A native thread created by LibreOfficeKit (we call it the soffice thread), where
- LibreOffice itself runs. It receives calls from LOKitThread, and may emit callback
+ LibreOffice itself runs. It receives calls from `LOKitThread`, and may emit callback
events as necessary.
-LOKitThread
-***********
+## LOKitThread
-LOKitThread (org.libreoffice.LOKitThread) communicates with LO via JNI (this can
-be done only for one thread) and processes events (defined in org.libreoffice.LOEvent)
+`LOKitThread` (`org.libreoffice.LOKitThread`) communicates with LO via JNI (this can
+be done only for one thread) and processes events (defined in `org.libreoffice.LOEvent`)
triggered from UI.
-Application Overview
-********************
+## Application Overview
-LibreOfficeMainActivity (org.libreoffice.LibreOfficeMainActivity) is the entry point
-of the application - everything starts up and tears down from here (onCreate, onResume,
-onPause, onStart, onStop, onDestroy).
+LibreOfficeMainActivity (`org.libreoffice.LibreOfficeMainActivity`) is the entry point
+of the application - everything starts up and tears down from here (`onCreate`, `onResume`,
+`onPause`, `onStart`, `onStop`, `onDestroy`).
-Document view
--------------
+### Document View
From here on one of the most interesting pieces are the classes around document view,
which includes listening to touch events, recalculating the viewport, tiled handling
and rendering the layers to the document.
-Viewport - the viewport is the currently visible part of the document. It is defined
+`Viewport` - the viewport is the currently visible part of the document. It is defined
by view rectangle and zoom.
-Layers - document view is rendered using many layers. Such layers are: document
+`Layers` - document view is rendered using many layers. Such layers are: document
background, scroll handles, and also the document tiles.
-Document view classes
----------------------
+### Document View Classes
-- LayerView (org.mozilla.gecko.gfx.LayerView) is the document view of the application.
- It uses the SurfaceView (android.view.SurfaceView) as the main surface to draw on
+- `LayerView` (`org.mozilla.gecko.gfx.LayerView`) is the document view of the application.
+ It uses the `SurfaceView` (`android.view.SurfaceView`) as the main surface to draw on
using OpenGL ES 2.
-- GLController (org.mozilla.gecko.gfx.GLController) - holder of the OpenGL context.
+- `GLController` (`org.mozilla.gecko.gfx.GLController`) - holder of the OpenGL context.
-- RenderControllerThread (org.mozilla.gecko.gfx.RenderControllerThread) executes the
+- `RenderControllerThread` (`org.mozilla.gecko.gfx.RenderControllerThread`) executes the
rendering requests through LayerRenderer.
-- LayerRenderer (org.mozilla.gecko.gfx.LayerRenderer) renders all the layers.
+- `LayerRenderer` (`org.mozilla.gecko.gfx.LayerRenderer`) renders all the layers.
-- GeckoLayerClient (org.mozilla.gecko.gfx.GeckoLayerClient) is the middle man of the
+- `GeckoLayerClient` (`org.mozilla.gecko.gfx.GeckoLayerClient`) is the middle man of the
application, which connects all the bits together. It is the document view layer
holder so the any management (including tiled rendering) usually go through this
- class. It listens to draw requests and viewport changes from PanZoomController
+ class. It listens to draw requests and viewport changes from `PanZoomController`
(see "Touch events").
-Touch events, scrolling and zooming
------------------------------------
+### Touch Events, Scrolling and Zooming
-The main class that handles the touch event, scrolling and zooming is JavaPanZoomController
-org.mozilla.gecko.gfx.JavaPanZoomController (implementation of PanZoomController interface).
+The main class that handles the touch event, scrolling and zooming is `JavaPanZoomController`
+`org.mozilla.gecko.gfx.JavaPanZoomController` (implementation of `PanZoomController` interface).
When the user performs a touch action, the document view needs to change, which means the
-viewport changes. JavaPanZoomController changes the viewport and signals the change through
-PanZoomTarget (org.mozilla.gecko.gfx.PanZoomTarget).
+viewport changes. `JavaPanZoomController` changes the viewport and signals the change through
+`PanZoomTarget` (`org.mozilla.gecko.gfx.PanZoomTarget`).
-TiledRendering
---------------
+### Tiled Rendering
Tiled rendering is a technique that splits the document to bitmaps of same size (typically
256x256) which are fetched on demand.
-In the application the ComposedTileLayer (org.mozilla.gecko.gfx.ComposedTileLayer) is the
+In the application the `ComposedTileLayer` (`org.mozilla.gecko.gfx.ComposedTileLayer`) is the
layer responsible for tracking and managing the tiles. Tiles are in this case also layers
-(sub layers?) implemented in SubTile (org.mozilla.gecko.gfx.SubTile), where each one is
+(sub layers?) implemented in `SubTile` (`org.mozilla.gecko.gfx.SubTile`), where each one is
responsible for one tile bitmap (actually OpenGL texture once it has been uploaded).
-When the viewport changes, the request for tile rechecking is send to LOKitThread (see
+When the viewport changes, the request for tile rechecking is send to `LOKitThread` (see
LOKitThread#tileReevaluationRequest), where the tiles are rechecked, add and removed if
necessary.
-CompositeTileLayer is actually an abstract class, which has two implementations. One is
-DynamicTileLayer (org.mozilla.gecko.gfx.DynamicTileLayer), which is used for main tile
-view of the document, and FixedZoomTileLayer (org.mozilla.gecko.gfx.FixedZoomTileLayer),
+`CompositeTileLayer` is actually an abstract class, which has two implementations. One is
+`DynamicTileLayer` (`org.mozilla.gecko.gfx.DynamicTileLayer`), which is used for main tile
+view of the document, and `FixedZoomTileLayer` (`org.mozilla.gecko.gfx.FixedZoomTileLayer`),
which just renders the tiles at a fixed zoom level. This is then used as a background
low resolution layer.
-Tile invalidation
------------------
+### Tile Invalidation
Tile can change in LibreOffice when user changes the content (adds, removes text or changes
the properties). In this case, an invalidation rectangle is signaled from LibreOffice, which
-includes a rectangle that needs to be invalidated. In this case LOKitThread gets this request
+includes a rectangle that needs to be invalidated. In this case `LOKitThread` gets this request
via callback, and rechecks all tiles if they need to be invalidated. For more details see
LOKitThread#tileInvalidation).
-Editing
-*******
+## Editing
For editing there are 2 coarse tasks that the LibreOffice app must do:
+
1. send input events to LibreOffice core (keyboard, touch and mouse)
2. listen to messages (provided via callback) from LibreOffice core and react accordingly
@@ -131,38 +121,35 @@ LO core follows. For example: when the user writes to the keyboard, key event is
an invalidation request from LO core follows. When user touches an image, a mouse event is
sent, and a "new graphic selection" message from LO core follows.
-All keyboard and touch events are sent to LOKitThread as LOEvents. In LOKitThread they are
-processed and sent to LibreOffice core. The touch events originate in JavaPanZoomController,
-the keyboard events in LOKitInputConnectionHandler (org.libreoffice.LOKitInputConnectionHandler),
+All keyboard and touch events are sent to `LOKitThread` as `LOEvents`. In `LOKitThread` they are
+processed and sent to LibreOffice core. The touch events originate in `JavaPanZoomController`,
+the keyboard events in `LOKitInputConnectionHandler` (`org.libreoffice.LOKitInputConnectionHandler`),
however there are other parts too - depending on the need.
-InvalidationHandler (org.libreoffice.InvalidationHandler) is the class that is responsible
+`InvalidationHandler` (`org.libreoffice.InvalidationHandler`) is the class that is responsible
to process messages from LibreOffice core and to track the state.
-Overlay
-*******
+## Overlay
Overlay elements like cursor and selections aren't drawn by the LO core, instead the core
only provides data (cursor position, selection rectangles) and the app needs to draw them.
-DocumentOverlay (org.libreoffice.overlay.DocumentOverlay) and DocumentOverlayView
-(org.libreoffice.overlay.DocumentOverlayView) are the classes that provide the overlay over
+`DocumentOverlay` (`org.libreoffice.overlay.DocumentOverlay`) and `DocumentOverlayView`
+(`org.libreoffice.overlay.DocumentOverlayView`) are the classes that provide the overlay over
the document, where selections and the cursor is drawn.
-Icons
-*****
+## Icons
App uses material design icons available at [1].
-[1] - https://www.google.com/design/icons/
+[1] - <https://www.google.com/design/icons/>
-Emulator and debugging notes
-****************************
+## Emulator and Debugging Notes
-For instructions on how to build for Android, see README.cross.
+For instructions on how to build for Android, see `README.cross`.
-* Getting something running
+### Getting Something Running
Attach your device, so 'adb devices' shows it. Then run:
@@ -173,7 +160,7 @@ Attach your device, so 'adb devices' shows it. Then run:
and if all goes well, you should have some nice debug output to enjoy when you
start the app.
-* Using the emulator
+### Using the Emulator
Create an AVD in the android UI, don't even try to get the data partition size
right in the GUI, that is doomed to producing an AVD that doesn't work.
@@ -183,103 +170,102 @@ Instead start it from the console:
where <Name> is the literal name of the AVD that you entered.
-[ In order to have proper acceleration, you need the 32-bit libGL.so:
+[ In order to have proper acceleration, you need the 32-bit `libGL.so`:
sudo zypper in Mesa-libGL-devel-32bit
and run emulator-arm after the installation. ]
-Then you can run ant/adb as described above.
+Then you can run `ant`/`adb` as described above.
After a while of this loop you might find that you have lost a lot of
-space on your emulator's or device's /data volume. You can do:
+space on your emulator's or device's `/data` volume. You can do:
adb shell stop; adb shell start
-Debugging
----------
+## Debugging
-First of all, you need to configure the build with --enable-debug or
---enable-dbgutil. You may want to provide --enable-symbols to limit debuginfo,
-like --enable-symbols="sw/" or so, in order to fit into the memory
+First of all, you need to configure the build with `--enable-debug` or
+`--enable-dbgutil`. You may want to provide `--enable-symbols` to limit debuginfo,
+like `--enable-symbols="sw/"` or so, in order to fit into the memory
during linking.
Building with all symbols is also possible but the linking is currently
slow (around 10 to 15 minutes) and you need lots of memory (around 16GB + some
swap).
-* Using ndk-gdb
+### Using ndk-gdb
-Direct support for using ndk-gdb has been removed from the build system. It is
+Direct support for using `ndk-gdb` has been removed from the build system. It is
recommended that you give the lldb debugger a try that has the benefit of being
nicely integrated into Android Studio (see below for instructions).
-If you nevertheless want to continue using ndk-gdb, use the following steps
-that are described in more detail here: https://stackoverflow.com/a/10539883
+If you nevertheless want to continue using `ndk-gdb`, use the following steps
+that are described in more detail here: <https://stackoverflow.com/a/10539883>
- - add android:debuggable="true" to AndroidManifest.xml
- - push gdbserver to device, launch and attach to application
- - forward debugging port from host to device
- - launch matching gdb on host and run following setup commands:
+- add `android:debuggable="true"` to `AndroidManifest.xml`
+- push `gdbserver` to device, launch and attach to application
+- forward debugging port from host to device
+- launch matching gdb on host and run following setup commands:
- set solib-search-path obj/local/<appAbi>
- file obj/local/<appAbi>/liblo-native-code.so
- target remote :<portused>
Pretty printers aren't loaded automatically due to the single shared
object, but you can still load them manually. E.g. to have a pretty-printer for
-rtl::OString, you need:
+`rtl::OString`, you need:
(gdb) python sys.path.insert(0, "/master/solenv/gdb")
(gdb) source /master/instdir/program/libuno_sal.so.3-gdb.py
-* Using Android Studio (and thus lldb)
+### Using Android Studio (and Thus lldb)
-Note that lldb might not yield the same results as ndk-gdb. If you suspect a
-problem with lldb, you can try to manually use ndk-gdb as described above.
-Using lldb from within Android Studio is more comfortable though and works like this:
+Note that lldb might not yield the same results as `ndk-gdb`. If you suspect a
+problem with `lldb`, you can try to manually use `ndk-gdb` as described above.
+Using `lldb` from within Android Studio is more comfortable though and works like this:
- - open android/source/build.gradle in Android Studio via File|New → Import Project
- - make sure you select the right build variant (strippedUIDebug is what you want)
- - use Run|Edit Configurations to create a new configuration of type "Android Native"
- - on tab "General" pick module "source"
- - on tab "Native Debugger" add android/source/obj/local/<hostarch> to
- the Symbol directories
- - on the LLDB startup commands tab add
- "command script import /path/to/solenv/lldb/libreoffice/LO.py"
- to get some pretty printing hooks for the various string classes
+- open `android/source/build.gradle` in Android Studio via File|New → Import Project
+- make sure you select the right build variant (`strippedUIDebug` is what you want)
+- use Run|Edit Configurations to create a new configuration of type "Android Native"
+ - on tab "General" pick module "source"
+ - on tab "Native Debugger" add `android/obj/local/<hostarch>` to
+ the Symbol directories
+ - on the LLDB startup commands tab add
+ "command script import `/path/to/solenv/lldb/libreoffice/LO.py`"
+ to get some pretty printing hooks for the various string classes
Then you can select your new configuration and use Run | Debug to launch it.
-Note that lldb doesn't initially stop execution, so if you want to add
+Note that `lldb` doesn't initially stop execution, so if you want to add
breakpoints using lldb prompt, you manually have to pause execution, then you
can switch to the lldb tab and add your breakpoints. However making use of the
editor just using File|Open .. to open the desired file in Android Studio and
then toggling the breakpoint by clicking on the margin is more comfortable.
-* Debugging the Java part
+### Debugging the Java Part
-Open android/source/build.gradle in Android studio via File|New → Import
+Open `android/source/build.gradle` in Android studio via File|New → Import
Project and you can use Android Studio's debugging interface.
Just make sure you pick the correct build variant (strippedUIDebug)
The alternative is to use the jdb command-line debugger. Steps to use it:
-1) Find out the JDWP ID of a debuggable application:
+1. Find out the JDWP ID of a debuggable application:
adb jdwp
-From the list of currently active JDWP processes, the last number is the just
+ From the list of currently active JDWP processes, the last number is the just
started debuggable application.
-2) Forward the remote JDWP port/process ID to a local port:
+2. Forward the remote JDWP port/process ID to a local port:
adb forward tcp:7777 jdwp:31739
-3) Connect to the running application:
+3. Connect to the running application:
jdb -sourcepath src/java/ -attach localhost:7777
Assuming that you're already in the LOAndroid3 directory in your shell.
-* Debugging the missing services
+### Debugging the Missing Services
Android library only include essential services that are compiled for
LibreOffice in order to reduce the size of the apk. When developing,
@@ -287,40 +273,40 @@ some services might become useful and we should add those services
to the combined library.
In order to identify missing services, we need to be able to receive
-SAL_INFO from cppuhelper/source/shlib.cxx in logcat and therefore identify
+`SAL_INFO` from `cppuhelper/source/shlib.cxx` in logcat and therefore identify
what services are missing. To do so, you may want add the following
when configuring the build.
--enable-symbols="cppuhelper/ sal/"
-[TODO: This is nonsense. --enable-symbols enables the -g option, not SAL_INFO.
-Perhaps this was a misunderstanding of meaning of --enable-selective-debuginfo,
+[TODO: This is nonsense. `--enable-symbols` enables the `-g` option, not `SAL_INFO`.
+Perhaps this was a misunderstanding of meaning of `--enable-selective-debuginfo`,
the old name for the option.]
Which services are combined in the android lib is determined by
solenv/bin/native-code.py
-* Common Errors / Gotchas
+### Common Errors / Gotchas
-lo_dlneeds: Could not read ELF header of /data/data/org.libreoffice...libfoo.so
- This (most likely) means that the install quietly failed, and that
-the file is truncated; check it out with adb shell ls -l /data/data/...
+ lo_dlneeds: Could not read ELF header of /data/data/org.libreoffice...libfoo.so
+This (most likely) means that the install quietly failed, and that
+the file is truncated; check it out with `adb shell ls -l /data/data/...`
-* Startup details
+### Startup Details
All Android apps are basically Java programs. They run "in" a Dalvik
(or on Android 5 or newer - ART) virtual machine. Yes, you can also
have apps where all *your* code is native code, written in a compiled
language like C or C++. But also such apps are actually started
-by system-provided Java bootstrapping code (NativeActivity) running
+by system-provided Java bootstrapping code (`NativeActivity`) running
in a Dalvik VM.
Such a native app (or actually, "activity") is not built as a
-executable program, but as a shared object. The Java NativeActivity
+executable program, but as a shared object. The Java `NativeActivity`
bootstrapper loads that shared object with dlopen.
-Anyway, our current "experimental" apps are not based on NativeActivity.
+Anyway, our current "experimental" apps are not based on `NativeActivity`.
They have normal Java code for the activity, and just call out to a single,
-app-specific native library (called liblo-native-code.so) to do all the
+app-specific native library (called `liblo-native-code.so`) to do all the
heavy lifting.
diff --git a/android/default-document/example.odt b/android/default-document/example.odt
index 2da7ce6e84d1..3aa6bb5119e9 100644
--- a/android/default-document/example.odt
+++ b/android/default-document/example.odt
Binary files differ
diff --git a/android/default-document/example_test.ods b/android/default-document/example_test.ods
new file mode 100644
index 000000000000..4ee7cb7e60ea
--- /dev/null
+++ b/android/default-document/example_test.ods
Binary files differ
diff --git a/android/source/AndroidManifest.xml b/android/source/AndroidManifest.xml
index 58da19119828..0a11a1d3654b 100644
--- a/android/source/AndroidManifest.xml
+++ b/android/source/AndroidManifest.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- android:installLocation="${installLocation}"
- package="org.libreoffice">
+ android:installLocation="${installLocation}">
<!-- App requires OpenGL ES 2.0 -->
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
@@ -9,13 +8,10 @@
<uses-feature android:name="android.hardware.usb.host" android:required="false"/>
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- <uses-permission android:name="android.permission.INTERNET" />
- <!-- extractNativeLibs="true" needed e.g. for NSS to load modules at runtime -->
<application
android:name=".LibreOfficeApplication"
android:allowBackup="true"
- android:extractNativeLibs="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/LibreOfficeTheme"
@@ -26,9 +22,9 @@
<!-- When changing android:windowSoftInputMode, please don't specify multiple "adjust..." or "state...". -->
<activity
android:name=".LibreOfficeMainActivity"
- android:label="@string/app_name"
android:configChanges="orientation|keyboard|keyboardHidden|screenLayout|uiMode|screenSize|smallestScreenSize"
- android:windowSoftInputMode="adjustResize" >
+ android:windowSoftInputMode="adjustResize"
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
@@ -49,9 +45,7 @@
<data android:mimeType="application/vnd.oasis.opendocument.text-flat-xml" />
<data android:mimeType="application/vnd.oasis.opendocument.graphics-flat-xml" />
<data android:mimeType="application/vnd.oasis.opendocument.presentation-flat-xml" />
- <!-- TODO: opening FODS documents crashes currently
<data android:mimeType="application/vnd.oasis.opendocument.spreadsheet-flat-xml" />
- -->
<!-- ODF templates -->
<data android:mimeType="application/vnd.oasis.opendocument.text-template"/>
@@ -73,7 +67,7 @@
<!-- OOXML -->
<data android:mimeType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
<data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.presentation" />
- <!-- Currently crashes. <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.slideshow"/> -->
+ <data android:mimeType="application/vnd.openxmlformats-officedocument.presentationml.slideshow" />
<data android:mimeType="application/vnd.openxmlformats-officedocument.wordprocessingml.document" />
<!-- OOXML templates -->
@@ -98,36 +92,19 @@
<activity
android:name=".SettingsActivity"
- android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
+ android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar"
android:label="@string/app_name_settings">
</activity>
<!-- Document Browser Activity -->
<activity android:name="org.libreoffice.ui.LibreOfficeUIActivity"
- android:label="@string/app_name" >
+ android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <!-- Document Provider Settings Activity -->
- <activity android:name=".storage.DocumentProviderSettingsActivity"
- android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
- android:label="@string/storage_provider_settings">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <activity android:name=".storage.external.BrowserSelectorActivity" >
- </activity>
-
- <activity android:name=".storage.external.DirectoryBrowserActivity"
- android:label="@string/directory_browser_label"
- android:windowSoftInputMode="stateHidden">
- </activity>
-
<activity android:name=".PresentationActivity"
android:screenOrientation="landscape" >
<meta-data
@@ -136,7 +113,7 @@
</activity>
<provider
- android:name="android.support.v4.content.FileProvider"
+ android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
diff --git a/android/source/Makefile b/android/source/Makefile
index 5d6603f94738..2c1d6f9f1cca 100644
--- a/android/source/Makefile
+++ b/android/source/Makefile
@@ -3,11 +3,12 @@ gb_Side:=host
include ../../config_host.mk
endif
-# The default target just builds.
+# The default target builds the APK and runs lint.
all: build-gradle
DISABLE_UI=TRUE
+BUILD_VARIANT=$(if $(DISABLE_UI),StrippedUI,FullUI)$(if $(ENABLE_ANDROID_EDITING),Editing)$(if $(ENABLE_RELEASE_BUILD),Release,Debug)
BOOTSTRAPDIR=../Bootstrap
include $(BOOTSTRAPDIR)/Makefile.shared
@@ -20,20 +21,20 @@ install:
@if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then echo ; echo 'Run it with "make run"' ; echo ; fi
uninstall:
- $(ANDROID_SDK_HOME)/platform-tools/adb uninstall $(ANDROID_PACKAGE_NAME)
+ $(ANDROID_SDK_DIR)/platform-tools/adb uninstall $(ANDROID_PACKAGE_NAME)
clean:
- rm -rf assets assets_fullUI assets_strippedUI jniLibs jniLibs_debug $(OBJLOCAL)
+ rm -rf assets assets_fullUI assets_strippedUI build jniLibs jniLibs_debug res_generated $(OBJLOCAL)
rm -f native-code.cxx
rm -f liboSettings.gradle
build-gradle: liboSettings.gradle local.properties link-so
ifeq ($(ENABLE_JAVA),TRUE)
- if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then ./gradlew $(if $(verbose),--info) $(if $(versionCode),-PcmdVersionCode=$(versionCode)) assemble$(if $(DISABLE_UI),StrippedUI,FullUI)$(if $(ENABLE_ANDROID_EDITING),Editing)$(if $(ENABLE_RELEASE_BUILD),Release,Debug) ; fi
+ if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then ./gradlew $(if $(verbose),--info) $(if $(versionCode),-PcmdVersionCode=$(versionCode)) assemble$(BUILD_VARIANT) lint$(BUILD_VARIANT) ; fi
endif
run:
- if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then $(ANDROID_SDK_HOME)/platform-tools/adb shell am start -n $(ANDROID_PACKAGE_NAME)/org.libreoffice.ui.LibreOfficeUIActivity ; fi
+ if test "$$ENABLE_ANDROID_LOK" != "TRUE" ; then $(ANDROID_SDK_DIR)/platform-tools/adb shell am start -n $(ANDROID_PACKAGE_NAME)/org.libreoffice.ui.LibreOfficeUIActivity ; fi
debugrun:
@echo "please debug with lldb from within Android Studio, or setup ndk-gdb manually (see android/README for details)"
diff --git a/android/source/build.gradle b/android/source/build.gradle
index 32de09f84749..8cbef7744d8e 100644
--- a/android/source/build.gradle
+++ b/android/source/build.gradle
@@ -2,24 +2,26 @@ apply plugin: 'com.android.application'
// buildhost settings - paths and the like
apply from: 'liboSettings.gradle'
-project.ext.set("archivesBaseName", "LibreOfficeViewer")
allprojects {
repositories {
- jcenter()
- google()
- flatDir {
- dirs "${liboWorkdir}/UnpackedTarball/owncloud_android_lib/build/outputs/aar"
+ mavenCentral()
+ maven {
+ url "https://ipv6.repo1.maven.org/maven2"
}
+ google()
}
}
//build-time dependencies - android plugin for gradle
buildscript {
repositories {
- jcenter()
+ mavenCentral()
+ maven {
+ url "https://ipv6.repo1.maven.org/maven2"
+ }
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.6.1'
+ classpath 'com.android.tools.build:gradle:8.3.2'
}
}
@@ -30,34 +32,36 @@ dependencies {
"libreoffice.jar",
"unoloader.jar"
])
- implementation(name:'owncloud_android_lib', ext:'aar')
- implementation 'com.android.support:design:27.1.1' // also pulls-in corresponding support libraries
- implementation 'com.android.support.constraint:constraint-layout:1.1.2'
+ implementation 'com.google.android.material:material:1.11.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation "androidx.multidex:multidex:2.0.1"
}
android {
- compileSdkVersion 28
- compileOptions {
- // silence some java-language features hints
- sourceCompatibility 6
+ namespace 'org.libreoffice'
+ compileSdk 34
+ buildFeatures {
+ buildConfig = true
}
// uses non-conventional source layout, so need to reconfigure accordingly
// ToDo move to conventional layout, so stuff can be stripped down.
sourceSets {
main.manifest.srcFile 'AndroidManifest.xml'
main.assets.srcDirs = ['assets']
- main.res.srcDirs = ['res']
+ main.res.srcDirs = ['res', 'res_generated']
main.java.srcDirs = ['../Bootstrap/src', 'src/java']
main.jniLibs.srcDirs = ["${liboJniLibsdir}"]
- main.jni.srcDirs = [] // don't attempt to build native-lib via gradle
// the configuration data that might be stripped or not
fullUI.assets.srcDirs 'assets_fullUI'
strippedUI.assets.srcDirs 'assets_strippedUI'
strippedUIEditing.assets.srcDirs 'assets_strippedUI'
}
defaultConfig {
- minSdkVersion 16
- targetSdkVersion 28
+ // minSdkVersion is set in liboSettings.gradle
+ targetSdkVersion 34
+ // multidex needed when > 65,536 methods referenced with minSdKVersion < 21
+ // s. https://developer.android.com/studio/build/multidex
+ multiDexEnabled true
vectorDrawables.useSupportLibrary = true
}
buildTypes {
@@ -81,16 +85,31 @@ android {
strippedUIEditing {
dimension "default"
buildConfigField 'boolean', 'ALLOW_EDITING', 'true'
- versionNameSuffix "-editing"
}
fullUI.dimension "default"
}
- lintOptions {
- // don't error-out on missing translations
- warning 'MissingTranslation'
+ lint {
+ warningsAsErrors true
+ // ignore missing or extra translations, since these are tracked/managed via Weblate
+ ignore 'ExtraTranslation', 'MissingTranslation'
+ // don't error-out on external updates (new gradle plugin, library versions
+ // or target API become available)
+ // don't error-out on TypographyEllipsis, since this can be introduced with
+ // new translations, and those are handled in Weblate
+ informational 'AndroidGradlePluginVersion', 'GradleDependency', 'NewerVersionAvailable', 'OldTargetApi', 'TypographyEllipsis'
+ // don't fail on pre-existing issues
+ // These should be dealt with at some point, though.
+ // To update lint-baseline.xml, just remove the file and run the build again.
+ baseline file("lint-baseline.xml")
+ // s.a. lint.xml that contains further config
}
}
+// show warnings about use of deprecated API
+tasks.withType(JavaCompile).configureEach {
+ options.deprecation = true
+}
+
/* remark inherited from makefile:
Then "assets". Let the directory structure under assets mimic
that under solver for now.
@@ -148,20 +167,21 @@ task copyUnpackAssets(type: Copy) {
task copyAssets(type: Copy) {
description "copies assets that can be accessed within the installed apk"
into 'assets'
- from("${liboInstdir}") {
- includes = ["LICENSE", "NOTICE"]
- rename "LICENSE", "license.txt"
- rename "NOTICE", "notice.txt"
- }
- from("${liboExampleDocument}") {
- rename ".*", "example.odt"
- }
- // include icons
+ // include icons, Impress styles and required .ui files
into ('share') {
into ('config') {
from ("${liboInstdir}/share/config")
- includes = ['images_**.zip']
+ includes = ['images_**.zip',
+ '**/simpress/**.xml',
+ '**/annotation.ui',
+ '**/hfmenubutton.ui',
+ '**/inforeadonlydialog.ui',
+ '**/pbmenubutton.ui',
+ '**/scrollbars.ui',
+ '**/tabbuttons.ui',
+ '**/tabviewbar.ui'
+ ]
}
}
@@ -186,14 +206,15 @@ task copyAssets(type: Copy) {
include '*.data'
}
}
- // documents with manual page break trigger attempt to read the ui file 'pagebreakmenu.ui'
- // would trigger a css::container::NoSuchElementException with osl_File_E_NOENT
- // if not present and since it is not caught would crash the app;
- // 'annotationmenu.ui' required to handle documents containing comments,
- // 'headerfootermenu.ui' when clicking inside header/footer of document
- into('config') {
- from "${liboInstdir}/share/config"
- include '**/pagebreakmenu.ui', '**/annotationmenu.ui', '**/headerfootermenu.ui'
+}
+
+task copyAppResources(type: Copy) {
+ description "copies documents to make them available as app resources"
+ into 'res_generated/raw'
+ from("${liboInstdir}") {
+ includes = ["LICENSE", "NOTICE"]
+ rename "LICENSE", "license.txt"
+ rename "NOTICE", "notice.txt"
}
}
@@ -263,6 +284,7 @@ task createRCfiles {
[Bootstrap]
LO_LIB_DIR=file://$APP_DATA_DIR/lib/
BRAND_BASE_DIR=file:///assets
+ BRAND_SHARE_SUBDIR=share
CONFIGURATION_LAYERS=xcsxcu:${BRAND_BASE_DIR}/share/registry res:${BRAND_BASE_DIR}/share/registry
URE_BIN_DIR=file:///assets/ure/bin/dir/nothing-here/we-can/exec-anyway
'''.stripIndent()
@@ -294,7 +316,8 @@ task createRCfiles {
preBuild.dependsOn 'createRCfiles',
'createStrippedConfigMain',
'createStrippedConfigRegistry',
- 'createFullConfig'
+ 'createFullConfig',
+ 'copyAppResources'
clean.dependsOn 'cleanCopyAssets',
'cleanCreateStrippedConfig',
diff --git a/android/source/gradle.properties b/android/source/gradle.properties
index ad1671ef57fd..19f2d673e497 100644
--- a/android/source/gradle.properties
+++ b/android/source/gradle.properties
@@ -1 +1,4 @@
+android.nonFinalResIds=false
+android.nonTransitiveRClass=false
+android.useAndroidX=true
org.gradle.jvmargs=-Xmx3072m
diff --git a/android/source/gradle/wrapper/gradle-wrapper.jar b/android/source/gradle/wrapper/gradle-wrapper.jar
index 8c0fb64a8698..033e24c4cdf4 100644
--- a/android/source/gradle/wrapper/gradle-wrapper.jar
+++ b/android/source/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/android/source/gradle/wrapper/gradle-wrapper.properties b/android/source/gradle/wrapper/gradle-wrapper.properties
index 7d1cfd365805..cdea548c75ee 100644
--- a/android/source/gradle/wrapper/gradle-wrapper.properties
+++ b/android/source/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
-#Tue Mar 03 14:01:57 CET 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionSha256Sum=c16d517b50dd28b3f5838f0e844b7520b8f1eb610f2f29de7e4e04a1b7c9c79b
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/android/source/gradlew b/android/source/gradlew
index 91a7e269e19d..fcb6fca147c0 100755
--- a/android/source/gradlew
+++ b/android/source/gradlew
@@ -1,79 +1,126 @@
-#!/usr/bin/env bash
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
-warn ( ) {
+warn () {
echo "$*"
-}
+} >&2
-die ( ) {
+die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MINGW* )
- msys=true
- ;;
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
-# For Cygwin, ensure paths are in UNIX format before anything is touched.
-if $cygwin ; then
- [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
-fi
-
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >&-
-APP_HOME="`pwd -P`"
-cd "$SAVED" >&-
-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -82,83 +129,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
-# For Cygwin, switch paths to Windows format before running java
-if $cygwin ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=$((i+1))
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- (0) set -- ;;
- (1) set -- "$args0" ;;
- (2) set -- "$args0" "$args1" ;;
- (3) set -- "$args0" "$args1" "$args2" ;;
- (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
-}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/android/source/gradlew.bat b/android/source/gradlew.bat
index 72d362dafd89..6689b85beecd 100755
--- a/android/source/gradlew.bat
+++ b/android/source/gradlew.bat
@@ -1,4 +1,20 @@
-@if "%DEBUG%" == "" @echo off
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -8,20 +24,24 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +55,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,44 +65,26 @@ echo location of your Java installation.
goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/android/source/ic_launcher-web.png b/android/source/ic_launcher-web.png
index e9dcfcacf844..82497c1ac299 100644
--- a/android/source/ic_launcher-web.png
+++ b/android/source/ic_launcher-web.png
Binary files differ
diff --git a/android/source/lint-baseline.xml b/android/source/lint-baseline.xml
new file mode 100644
index 000000000000..01fdd6f8d234
--- /dev/null
+++ b/android/source/lint-baseline.xml
@@ -0,0 +1,2341 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 8.3.2" type="baseline" client="gradle" dependencies="false" name="AGP (8.3.2)" variant="all" version="8.3.2">
+
+ <issue
+ id="ScopedStorage"
+ message="WRITE_EXTERNAL_STORAGE is deprecated (and is not granted) when targeting Android 13+. If you need to write to shared storage, use the `MediaStore.createWriteRequest` intent."
+ errorLine1=" &lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="AndroidManifest.xml"
+ line="10"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="ScrollViewSize"
+ message="This LinearLayout should use `android:layout_height=&quot;wrap_content&quot;`"
+ errorLine1=" android:layout_height=&quot;match_parent&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="311"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="ScrollViewSize"
+ message="This LinearLayout should use `android:layout_height=&quot;wrap_content&quot;`"
+ errorLine1=" android:layout_height=&quot;match_parent&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="378"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="CanvasSize"
+ message="Calling `Canvas.getWidth()` is usually wrong; you should be calling `getWidth()` instead"
+ errorLine1=" int horizontalMargin = (int) (canvas.getWidth()*0.1);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ui/PageView.java"
+ line="55"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="CanvasSize"
+ message="Calling `Canvas.getWidth()` is usually wrong; you should be calling `getWidth()` instead"
+ errorLine1=" new Rect(horizontalMargin,verticalMargin,canvas.getWidth()-horizontalMargin,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ui/PageView.java"
+ line="59"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="CanvasSize"
+ message="Calling `Canvas.getHeight()` is usually wrong; you should be calling `getHeight()` instead"
+ errorLine1=" canvas.getHeight()-verticalMargin),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ui/PageView.java"
+ line="60"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="CommitPrefEdits"
+ message="`SharedPreferences.edit()` without a corresponding `commit()` or `apply()` call"
+ errorLine1=" preferences.edit().putString(SELECTED_LANG, lang);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/LocaleHelper.java"
+ line="49"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" return String.format(&quot;TileIdentifier (%d, %d) z=%f s=(%d, %d)&quot;, x, y, zoom, size.width, size.height);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/TileIdentifier.java"
+ line="88"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="AppBundleLocaleChanges"
+ message="Found dynamic locale changes, but did not find corresponding Play Core library calls for downloading languages and splitting by language is not disabled in the `bundle` configuration"
+ errorLine1=" cfg.locale = locale;"
+ errorLine2=" ~~~~~~">
+ <location
+ file="src/java/org/libreoffice/LocaleHelper.java"
+ line="40"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+ errorLine1=" final View headerPopupView = inflater.inflate(R.layout.calc_header_popup, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="src/java/org/libreoffice/overlay/CalcHeadersController.java"
+ line="118"
+ column="87"/>
+ </issue>
+
+ <issue
+ id="InflateParams"
+ message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
+ errorLine1=" view = layoutInflater.inflate(R.layout.document_part_list_layout, null);"
+ errorLine2=" ~~~~">
+ <location
+ file="src/java/org/libreoffice/DocumentPartViewListAdapter.java"
+ line="36"
+ column="79"/>
+ </issue>
+
+ <issue
+ id="QueryPermissionsNeeded"
+ message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details"
+ errorLine1=" if (takePictureIntent.resolveActivity(mContext.getPackageManager()) != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/FormattingController.java"
+ line="370"
+ column="31"/>
+ </issue>
+
+ <issue
+ id="QueryPermissionsNeeded"
+ message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details"
+ errorLine1=" .queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/FormattingController.java"
+ line="386"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="UnsupportedChromeOsCameraSystemFeature"
+ message="You should look for any camera available on the device, not just the rear"
+ errorLine1=" if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/FormattingController.java"
+ line="363"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="SpUsage"
+ message="Should use &quot;`sp`&quot; instead of &quot;`dp`&quot; for text sizes"
+ errorLine1=" android:textSize=&quot;14dp&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="77"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="DiscouragedApi"
+ message="Should not restrict activity to fixed orientation. This may not be suitable for different form factors, causing the app to be letterboxed."
+ errorLine1=" android:screenOrientation=&quot;landscape&quot; >"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="AndroidManifest.xml"
+ line="109"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="DiscouragedApi"
+ message="Use of this function is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code. It is much more efficient to retrieve resources by identifier (e.g. `R.foo.bar`) than by name (e.g. `getIdentifier(&quot;bar&quot;, &quot;foo&quot;, null)`)."
+ errorLine1=" int resourceID = resources.getIdentifier(name, &quot;drawable&quot;, packageName);"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/mozilla/gecko/gfx/LayerView.java"
+ line="227"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="SetJavaScriptEnabled"
+ message="Using `setJavaScriptEnabled` can introduce XSS vulnerabilities into your application, review carefully"
+ errorLine1=" mWebView.getSettings().setJavaScriptEnabled(true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/PresentationActivity.java"
+ line="39"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" mLayerClient.setViewportSize(new FloatSize(right - left, bottom - top), true);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/mozilla/gecko/gfx/LayerView.java"
+ line="293"
+ column="42"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" canvas.drawBitmap(bmp, new Rect(0, 0, bmp.getWidth(), bmp.getHeight()),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ui/PageView.java"
+ line="58"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" new Rect(horizontalMargin,verticalMargin,canvas.getWidth()-horizontalMargin,"
+ errorLine2=" ^">
+ <location
+ file="src/java/org/libreoffice/ui/PageView.java"
+ line="59"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="DrawAllocation"
+ message="Avoid object allocations during draw/layout operations (preallocate and reuse instead)"
+ errorLine1=" canvas.drawText(getContext().getString(R.string.bmp_null), 100, 100, new Paint());"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ui/PageView.java"
+ line="64"
+ column="82"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" ColorPaletteAdapter.this.notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ColorPaletteAdapter.java"
+ line="118"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NotifyDataSetChanged"
+ message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort."
+ errorLine1=" ColorPickerAdapter.this.notifyDataSetChanged();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ColorPickerAdapter.java"
+ line="147"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `ScrollView`: `layout_weight`"
+ errorLine1=" android:layout_weight=&quot;0.25&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="312"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `ScrollView`: `layout_weight`"
+ errorLine1=" android:layout_weight=&quot;0.5&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="379"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_below`"
+ errorLine1=" android:layout_below=&quot;@id/fontColorView&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_color_picker.xml"
+ line="63"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteLayoutParam"
+ message="Invalid layout param in a `LinearLayout`: `layout_alignParentBottom`"
+ errorLine1=" android:layout_alignParentBottom=&quot;true&quot;>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_color_picker.xml"
+ line="64"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ObsoleteSdkInt"
+ message="Unnecessary; SDK_INT is always >= 19"
+ errorLine1="@TargetApi(19)"
+ errorLine2="~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/PDFDocumentAdapter.java"
+ line="20"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UseCompoundDrawables"
+ message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
+ errorLine1="&lt;LinearLayout"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="res/layout/document_part_list_layout.xml"
+ line="2"
+ column="2"/>
+ </issue>
+
+ <issue
+ id="VectorPath"
+ message="Very long vector path (871 characters), which is bad for performance. Considering reducing precision, removing minor details or rasterizing vector."
+ errorLine1=" android:pathData=&quot;M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z&quot;/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/drawable/ic_settings_24dp.xml"
+ line="8"
+ column="27"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_height` of `0dp` instead of `wrap_content` for better performance"
+ errorLine1=" android:layout_height=&quot;wrap_content&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="73"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="InefficientWeight"
+ message="Use a `layout_height` of `0dp` instead of `match_parent` for better performance"
+ errorLine1=" android:layout_height=&quot;match_parent&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="66"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="NestedWeights"
+ message="Nested weights are bad for performance"
+ errorLine1=" android:layout_weight=&quot;0.25&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="74"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `#fff` with a theme that also paints a background (inferred theme is `@style/LibreOfficeTheme`)"
+ errorLine1=" android:background=&quot;#fff&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_main.xml"
+ line="8"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `@color/doorhanger_background_dark` with a theme that also paints a background (inferred theme is `@style/LibreOfficeTheme`)"
+ errorLine1=" android:background=&quot;@color/doorhanger_background_dark&quot;>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/calc_header_popup.xml"
+ line="5"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `#aaa` with a theme that also paints a background (inferred theme is `@style/LibreOfficeTheme`)"
+ errorLine1=" android:background=&quot;#aaa&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/main.xml"
+ line="12"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?attr/colorPrimary` with a theme that also paints a background (inferred theme is `@style/LibreOfficeTheme`)"
+ errorLine1=" android:background=&quot;?attr/colorPrimary&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="10"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="Overdraw"
+ message="Possible overdraw: Root element paints background `?attr/colorPrimary` with a theme that also paints a background (inferred theme is `@style/LibreOfficeTheme`)"
+ errorLine1=" android:background=&quot;?attr/colorPrimary&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_color_picker.xml"
+ line="9"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.background` appears to be unused">
+ <location
+ file="res/drawable-mdpi/background.png"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.background_light` appears to be unused"
+ errorLine1=" &lt;color name=&quot;background_light&quot;>#FAFAFA&lt;/color> &lt;!--Material Grey 50-->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="12"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.background_normal` appears to be unused"
+ errorLine1=" &lt;color name=&quot;background_normal&quot;>#F5F5F5&lt;/color> &lt;!--Material Grey 100-->"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="13"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.background_private` appears to be unused"
+ errorLine1=" &lt;color name=&quot;background_private&quot;>#FF292C29&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="14"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.background_tabs` appears to be unused"
+ errorLine1=" &lt;color name=&quot;background_tabs&quot;>#FF363B40&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="15"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight&quot;>#33000000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="16"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_focused` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_focused&quot;>#1A000000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="17"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_dark` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_dark&quot;>#33FFFFFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="18"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_dark_focused` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_dark_focused&quot;>#1AFFFFFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="19"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_shaped` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_shaped&quot;>#FF696D71&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="22"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_shaped_focused` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_shaped_focused&quot;>#FF565B60&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="25"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_nav` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_nav&quot;>#FFA5ACB2&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="28"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_nav_focused` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_nav_focused&quot;>#FFB9C1C7&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="31"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_nav_pb` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_nav_pb&quot;>#FF545654&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="34"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.highlight_nav_focused_pb` appears to be unused"
+ errorLine1=" &lt;color name=&quot;highlight_nav_focused_pb&quot;>#FF3F423F&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="37"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_primary` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_primary&quot;>#222222&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="43"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_secondary` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_secondary&quot;>#777777&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="44"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_tertiary` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_tertiary&quot;>#9198A1&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="45"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_primary_inverse` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_primary_inverse&quot;>#FFFFFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="48"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_secondary_inverse` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_secondary_inverse&quot;>#DDDDDD&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="49"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_tertiary_inverse` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_tertiary_inverse&quot;>#A4A7A9&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="50"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_primary_disable_only` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_primary_disable_only&quot;>#999999&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="53"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_hint` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_hint&quot;>#666666&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="56"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_hint_inverse` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_hint_inverse&quot;>#7F828A&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="57"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_highlight` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_highlight&quot;>#FF9500&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="60"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_highlight_inverse` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_highlight_inverse&quot;>#D06BFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="61"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.text_color_link` appears to be unused"
+ errorLine1=" &lt;color name=&quot;text_color_link&quot;>#22629E&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="64"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.splash_background` appears to be unused"
+ errorLine1=" &lt;color name=&quot;splash_background&quot;>#000000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="66"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.splash_msgfont` appears to be unused"
+ errorLine1=" &lt;color name=&quot;splash_msgfont&quot;>#ffffff&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="67"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.splash_urlfont` appears to be unused"
+ errorLine1=" &lt;color name=&quot;splash_urlfont&quot;>#000000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="68"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.splash_content` appears to be unused"
+ errorLine1=" &lt;color name=&quot;splash_content&quot;>#ffffff&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="69"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.doorhanger_text` appears to be unused"
+ errorLine1=" &lt;color name=&quot;doorhanger_text&quot;>#FF222222&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="71"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.doorhanger_link` appears to be unused"
+ errorLine1=" &lt;color name=&quot;doorhanger_link&quot;>#FF2AA1FE&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="72"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.doorhanger_divider_dark` appears to be unused"
+ errorLine1=" &lt;color name=&quot;doorhanger_divider_dark&quot;>#FFB3C2CE&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="74"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.validation_message_text` appears to be unused"
+ errorLine1=" &lt;color name=&quot;validation_message_text&quot;>#ffffff&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="77"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_text_highlight` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_text_highlight&quot;>#FFFF9500&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="78"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_text_highlight_pb` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_text_highlight_pb&quot;>#FFD06BFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="79"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.suggestion_primary` appears to be unused"
+ errorLine1=" &lt;color name=&quot;suggestion_primary&quot;>#dddddd&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="80"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.suggestion_pressed` appears to be unused"
+ errorLine1=" &lt;color name=&quot;suggestion_pressed&quot;>#bbbbbb&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="81"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.tab_row_pressed` appears to be unused"
+ errorLine1=" &lt;color name=&quot;tab_row_pressed&quot;>#4D000000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="82"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.dialogtitle_textcolor` appears to be unused"
+ errorLine1=" &lt;color name=&quot;dialogtitle_textcolor&quot;>#ffffff&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="83"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.textbox_background` appears to be unused"
+ errorLine1=" &lt;color name=&quot;textbox_background&quot;>#FFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="85"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.textbox_background_disabled` appears to be unused"
+ errorLine1=" &lt;color name=&quot;textbox_background_disabled&quot;>#DDD&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="86"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.textbox_stroke` appears to be unused"
+ errorLine1=" &lt;color name=&quot;textbox_stroke&quot;>#000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="87"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.textbox_stroke_disabled` appears to be unused"
+ errorLine1=" &lt;color name=&quot;textbox_stroke_disabled&quot;>#666&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="88"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_urltext` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_urltext&quot;>#A6A6A6&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="90"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_domaintext` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_domaintext&quot;>#000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="91"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_domaintext_private` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_domaintext_private&quot;>#FFF&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="92"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_blockedtext` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_blockedtext&quot;>#b14646&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="93"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.url_bar_shadow` appears to be unused"
+ errorLine1=" &lt;color name=&quot;url_bar_shadow&quot;>#12000000&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="94"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.home_last_tab_bar_bg` appears to be unused"
+ errorLine1=" &lt;color name=&quot;home_last_tab_bar_bg&quot;>#FFF5F7F9&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="96"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.color.panel_grid_item_image_background` appears to be unused"
+ errorLine1=" &lt;color name=&quot;panel_grid_item_image_background&quot;>#D1D9E1&lt;/color>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/colors.xml"
+ line="98"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.dimen.activity_horizontal_margin` appears to be unused"
+ errorLine1=" &lt;dimen name=&quot;activity_horizontal_margin&quot;>16dp&lt;/dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/dimens.xml"
+ line="3"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.dimen.activity_vertical_margin` appears to be unused"
+ errorLine1=" &lt;dimen name=&quot;activity_vertical_margin&quot;>16dp&lt;/dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/dimens.xml"
+ line="4"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.dimen.text_selection_handle_width` appears to be unused"
+ errorLine1=" &lt;dimen name=&quot;text_selection_handle_width&quot;>30dp&lt;/dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/dimens.xml"
+ line="5"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.dimen.text_selection_handle_height` appears to be unused"
+ errorLine1=" &lt;dimen name=&quot;text_selection_handle_height&quot;>44dp&lt;/dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/dimens.xml"
+ line="6"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.dimen.text_selection_handle_shadow` appears to be unused"
+ errorLine1=" &lt;dimen name=&quot;text_selection_handle_shadow&quot;>2dp&lt;/dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/dimens.xml"
+ line="7"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.dimen.file_icon_width` appears to be unused"
+ errorLine1=" &lt;dimen name=&quot;file_icon_width&quot;>32dp&lt;/dimen>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/dimens.xml"
+ line="10"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.layout.document_viewer` appears to be unused"
+ errorLine1="&lt;RelativeLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+ errorLine2="^">
+ <location
+ file="res/layout/document_viewer.xml"
+ line="8"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.ic_menu` appears to be unused"
+ errorLine1="&lt;bitmap xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+ errorLine2="^">
+ <location
+ file="res/drawable-hdpi/ic_menu.xml"
+ line="3"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.ic_menu_black_24dp` appears to be unused">
+ <location
+ file="res/drawable-xxxhdpi/ic_menu_black_24dp.png"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.ic_settings_24dp` appears to be unused"
+ errorLine1="&lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+ errorLine2="^">
+ <location
+ file="res/drawable/ic_settings_24dp.xml"
+ line="1"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.ic_sort_24dp` appears to be unused"
+ errorLine1="&lt;vector android:autoMirrored=&quot;true&quot; android:height=&quot;24dp&quot;"
+ errorLine2="^">
+ <location
+ file="res/drawable/ic_sort_24dp.xml"
+ line="9"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.light_view_as_grid` appears to be unused">
+ <location
+ file="res/drawable-hdpi/light_view_as_grid.png"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.light_view_as_list` appears to be unused">
+ <location
+ file="res/drawable-hdpi/light_view_as_list.png"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.layout.main` appears to be unused"
+ errorLine1="&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+ errorLine2="^">
+ <location
+ file="res/layout/main.xml"
+ line="9"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.drawable.shadow` appears to be unused">
+ <location
+ file="res/drawable-mdpi/shadow.png"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.layout.text_selection_handles` appears to be unused"
+ errorLine1="&lt;merge xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;"
+ errorLine2="^">
+ <location
+ file="res/layout/text_selection_handles.xml"
+ line="6"
+ column="1"/>
+ </issue>
+
+ <issue
+ id="UnusedResources"
+ message="The resource `R.style.LibreOfficeTheme_NavigationView` appears to be unused"
+ errorLine1=" &lt;style name=&quot;LibreOfficeTheme.NavigationView&quot;>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/values/themes.xml"
+ line="17"
+ column="12"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `ScrollView` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" &lt;ScrollView"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="55"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `ScrollView` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" &lt;ScrollView"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="193"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `ScrollView` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" &lt;ScrollView"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="305"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="UselessParent"
+ message="This `ScrollView` layout or its `LinearLayout` parent is unnecessary"
+ errorLine1=" &lt;ScrollView"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="373"
+ column="26"/>
+ </issue>
+
+ <issue
+ id="TooDeepLayout"
+ message="`toolbar_bottom.xml` has more than 10 levels, bad for performance"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="70"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="IconLocation"
+ message="Found bitmap drawable `res/drawable/calc.png` in densityless folder">
+ <location
+ file="res/drawable/calc.png"/>
+ </issue>
+
+ <issue
+ id="IconLocation"
+ message="Found bitmap drawable `res/drawable/draw.png` in densityless folder">
+ <location
+ file="res/drawable/draw.png"/>
+ </issue>
+
+ <issue
+ id="IconLocation"
+ message="Found bitmap drawable `res/drawable/dummy_page.png` in densityless folder">
+ <location
+ file="res/drawable/dummy_page.png"/>
+ </issue>
+
+ <issue
+ id="IconLocation"
+ message="Found bitmap drawable `res/drawable/impress.png` in densityless folder">
+ <location
+ file="res/drawable/impress.png"/>
+ </issue>
+
+ <issue
+ id="IconLocation"
+ message="Found bitmap drawable `res/drawable/writer.png` in densityless folder">
+ <location
+ file="res/drawable/writer.png"/>
+ </issue>
+
+ <issue
+ id="IconDensities"
+ message="Missing the following drawables in `drawable-hdpi`: background.png, decrementindent.png, handle_image_end.png, handle_image_middle.png, handle_image_start.png... (22 more)">
+ <location
+ file="res/drawable-hdpi"/>
+ </issue>
+
+ <issue
+ id="IconDensities"
+ message="Missing the following drawables in `drawable-mdpi`: decrementindent.png, handle_alias_end.xml, handle_alias_middle.xml, handle_alias_start.xml, handle_image_end.png... (33 more)">
+ <location
+ file="res/drawable-mdpi"/>
+ </issue>
+
+ <issue
+ id="IconDensities"
+ message="Missing the following drawables in `drawable-xhdpi`: background.png, decrementindent.png, handle_alias_end.xml, handle_alias_middle.xml, handle_alias_start.xml... (32 more)">
+ <location
+ file="res/drawable-xhdpi"/>
+ </issue>
+
+ <issue
+ id="IconMissingDensityFolder"
+ message="Missing density variation folders in `res`: drawable-xxhdpi">
+ <location
+ file="res"/>
+ </issue>
+
+ <issue
+ id="AlwaysShowAction"
+ message="Prefer &quot;`ifRoom`&quot; instead of &quot;`always`&quot;"
+ errorLine1=" app:showAsAction=&quot;always&quot;/>"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/menu/main.xml"
+ line="14"
+ column="15"/>
+ <location
+ file="res/menu/main.xml"
+ line="20"
+ column="15"/>
+ <location
+ file="res/menu/main.xml"
+ line="26"
+ column="15"/>
+ <location
+ file="res/menu/main.xml"
+ line="32"
+ column="13"/>
+ <location
+ file="res/menu/main.xml"
+ line="112"
+ column="13"/>
+ <location
+ file="res/menu/main.xml"
+ line="118"
+ column="13"/>
+ <location
+ file="res/menu/main.xml"
+ line="124"
+ column="13"/>
+ <location
+ file="res/menu/main.xml"
+ line="130"
+ column="13"/>
+ <location
+ file="res/menu/main.xml"
+ line="140"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/calc_header_popup.xml"
+ line="73"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/password_dialog.xml"
+ line="6"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="454"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="493"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="533"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="543"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="Autofill"
+ message="Missing `autofillHints` attribute"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="553"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ReportShortcutUsage"
+ message="Calling this method indicates use of dynamic shortcuts, but there are no calls to methods that track shortcut usage, such as `pushDynamicShortcut` or `reportShortcutUsed`. Calling these methods is recommended, as they track shortcut usage and allow launchers to adjust which shortcuts appear based on activation history. Please see https://developer.android.com/develop/ui/views/launch/shortcuts/managing-shortcuts#track-usage"
+ errorLine1=" shortcutManager.setDynamicShortcuts(shortcuts);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/ui/LibreOfficeUIActivity.java"
+ line="430"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/overlay/CalcHeadersView.java"
+ line="69"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view `LayerView` overrides `onTouchEvent` but not `performClick`"
+ errorLine1=" public boolean onTouchEvent(MotionEvent event) {"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="src/java/org/mozilla/gecko/gfx/LayerView.java"
+ line="115"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`OnSlideSwipeListener#onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent me) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="src/java/org/mozilla/gecko/OnSlideSwipeListener.java"
+ line="89"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="Custom view ``WebView`` has `setOnTouchListener` called on it but does not override `performClick`"
+ errorLine1=" mWebView.setOnTouchListener(new View.OnTouchListener() {"
+ errorLine2=" ^">
+ <location
+ file="src/java/org/libreoffice/PresentationActivity.java"
+ line="40"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/PresentationActivity.java"
+ line="42"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="ClickableViewAccessibility"
+ message="`onTouch` should call `View#performClick` when a click is detected"
+ errorLine1=" public boolean onTouch(View v, MotionEvent event) {"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="src/java/org/libreoffice/PresentationActivity.java"
+ line="77"
+ column="28"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;com.google.android.material.floatingactionbutton.FloatingActionButton"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="137"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;com.google.android.material.floatingactionbutton.FloatingActionButton"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="169"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;com.google.android.material.floatingactionbutton.FloatingActionButton"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="201"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;com.google.android.material.floatingactionbutton.FloatingActionButton"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="233"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/colorbox.xml"
+ line="6"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageView"
+ errorLine2=" ~~~~~~~~~">
+ <location
+ file="res/layout/document_part_list_layout.xml"
+ line="10"
+ column="6"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/presentation_mode.xml"
+ line="16"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/presentation_mode.xml"
+ line="25"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="70"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="80"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="90"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="100"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="110"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="140"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="150"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="160"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="170"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="207"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="217"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="227"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="237"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="253"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="263"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="273"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="283"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="315"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="325"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="335"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="345"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="355"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="398"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="427"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="503"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="511"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="519"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="563"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="ContentDescription"
+ message="Missing `contentDescription` attribute on image"
+ errorLine1=" &lt;ImageButton"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_color_picker.xml"
+ line="30"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="111"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="143"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="175"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="207"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_document_browser.xml"
+ line="239"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/colorbox.xml"
+ line="11"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="30"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="64"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="95"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="KeyboardInaccessibleWidget"
+ message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
+ errorLine1=" android:clickable=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="126"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="LabelFor"
+ message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/activity_main.xml"
+ line="42"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="LabelFor"
+ message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/activity_main.xml"
+ line="52"
+ column="18"/>
+ </issue>
+
+ <issue
+ id="LabelFor"
+ message="Missing accessibility label: provide either a view with an `android:labelFor` that references this view or provide an `android:hint`"
+ errorLine1=" &lt;EditText"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="454"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;Rows:&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;Rows:&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="16"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;+&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;+&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="32"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;3&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;3&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="45"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;-&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;-&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="60"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;Columns:&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;Columns:&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="77"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;-&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;-&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="90"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;3&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;3&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="108"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="HardcodedText"
+ message="Hardcoded string &quot;+&quot;, should use `@string` resource"
+ errorLine1=" android:text=&quot;+&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="122"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/slide_show_nav_back` can overlap `@id/slide_show_nav_prev` if @string/slideshow_action_back grows due to localized text expansion"
+ errorLine1=" &lt;Button"
+ errorLine2=" ~~~~~~">
+ <location
+ file="res/layout/presentation_mode.xml"
+ line="34"
+ column="10"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`TextView-1` can overlap `@id/font_color_picker_button` if @string/font_color grows due to localized text expansion"
+ errorLine1=" &lt;TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="386"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`TextView-1` can overlap `@id/font_back_color_picker_button` if @string/highlight_color grows due to localized text expansion"
+ errorLine1=" &lt;TextView"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="415"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="RelativeOverlap"
+ message="`@id/button_auto_color` can overlap `@id/button_go_back_color_picker` if @string/automatic grows due to localized text expansion"
+ errorLine1=" &lt;Button"
+ errorLine2=" ~~~~~~">
+ <location
+ file="res/layout/toolbar_color_picker.xml"
+ line="38"
+ column="14"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_toRightOf`; already defining `layout_toEndOf` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_toRightOf=&quot;@+id/calc_header_top_left&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_main.xml"
+ line="78"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_toRightOf`; already defining `layout_toEndOf` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_toRightOf=&quot;@+id/calc_header_row&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/activity_main.xml"
+ line="94"
+ column="21"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_marginRight`; already defining `layout_marginEnd` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_marginRight=&quot;@dimen/file_icon_margin_end&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/item_recent_files.xml"
+ line="26"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_marginLeft`; already defining `layout_marginStart` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_marginLeft=&quot;8dp&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="14"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_marginRight`; already defining `layout_marginEnd` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_marginRight=&quot;8dp&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="27"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_marginLeft`; already defining `layout_marginStart` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_marginLeft=&quot;8dp&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="75"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_marginRight`; already defining `layout_marginEnd` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_marginRight=&quot;8dp&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/number_picker.xml"
+ line="120"
+ column="9"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_alignParentRight`; already defining `layout_alignParentEnd` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_alignParentRight=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/presentation_mode.xml"
+ line="21"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_alignParentRight`; already defining `layout_alignParentEnd` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_alignParentRight=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/presentation_mode.xml"
+ line="31"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Redundant attribute `layout_alignParentLeft`; already defining `layout_alignParentStart` with `targetSdkVersion` 34"
+ errorLine1=" android:layout_alignParentLeft=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/presentation_mode.xml"
+ line="38"
+ column="13"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Consider replacing `android:layout_alignParentLeft` with `android:layout_alignParentStart=&quot;true&quot;` to better support right-to-left layouts"
+ errorLine1=" android:layout_alignParentLeft=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="395"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Consider replacing `android:layout_alignParentRight` with `android:layout_alignParentEnd=&quot;true&quot;` to better support right-to-left layouts"
+ errorLine1=" android:layout_alignParentRight=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="405"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Consider replacing `android:layout_alignParentLeft` with `android:layout_alignParentStart=&quot;true&quot;` to better support right-to-left layouts"
+ errorLine1=" android:layout_alignParentLeft=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="424"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Consider replacing `android:layout_alignParentRight` with `android:layout_alignParentEnd=&quot;true&quot;` to better support right-to-left layouts"
+ errorLine1=" android:layout_alignParentRight=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_bottom.xml"
+ line="434"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="RtlHardcoded"
+ message="Consider replacing `android:layout_alignParentRight` with `android:layout_alignParentEnd=&quot;true&quot;` to better support right-to-left layouts"
+ errorLine1=" android:layout_alignParentRight=&quot;true&quot;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="res/layout/toolbar_color_picker.xml"
+ line="40"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="RtlEnabled"
+ message="The project references RTL attributes, but does not explicitly enable or disable RTL support with `android:supportsRtl` in the manifest">
+ <location
+ file="AndroidManifest.xml"/>
+ </issue>
+
+</issues>
diff --git a/android/source/lint.xml b/android/source/lint.xml
new file mode 100644
index 000000000000..bfcae7ec03cf
--- /dev/null
+++ b/android/source/lint.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+ <!-- Disable check for extra resources in translations, Weblate takes care of
+ removing these. -->
+ <issue id="UnusedResources">
+ <ignore path="res/values-*/strings.xml" />
+ </issue>
+</lint>
+
diff --git a/android/source/res/drawable-hdpi/action_search.png b/android/source/res/drawable-hdpi/action_search.png
deleted file mode 100644
index e6b70451863a..000000000000
--- a/android/source/res/drawable-hdpi/action_search.png
+++ /dev/null
Binary files differ
diff --git a/android/source/res/drawable-hdpi/action_search_light.png b/android/source/res/drawable-hdpi/action_search_light.png
deleted file mode 100644
index f12e005ebe83..000000000000
--- a/android/source/res/drawable-hdpi/action_search_light.png
+++ /dev/null
Binary files differ
diff --git a/android/source/res/drawable-hdpi/ic_folder_48dp.xml b/android/source/res/drawable-hdpi/ic_folder_48dp.xml
new file mode 100644
index 000000000000..7eec9b367f00
--- /dev/null
+++ b/android/source/res/drawable-hdpi/ic_folder_48dp.xml
@@ -0,0 +1,5 @@
+<vector android:autoMirrored="true" android:height="48dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="@color/toolbar_foreground" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
+</vector>
diff --git a/android/source/res/drawable-hdpi/ic_keyboard.xml b/android/source/res/drawable-hdpi/ic_keyboard.xml
index 00902169d505..2aea0f7597a7 100644
--- a/android/source/res/drawable-hdpi/ic_keyboard.xml
+++ b/android/source/res/drawable-hdpi/ic_keyboard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_keyboard_black_24dp"
- android:tint="@color/toolbar_foreground"/> \ No newline at end of file
+ android:src="@drawable/ic_keyboard_black__24dp"
+ android:tint="@color/toolbar_foreground"/>
diff --git a/android/source/res/drawable-hdpi/lo_icon.png b/android/source/res/drawable-hdpi/lo_icon.png
deleted file mode 100644
index d03373b9c2ee..000000000000
--- a/android/source/res/drawable-hdpi/lo_icon.png
+++ /dev/null
Binary files differ
diff --git a/android/source/res/drawable-mdpi/lo_icon.png b/android/source/res/drawable-mdpi/lo_icon.png
deleted file mode 100644
index 48e90bd1fdc5..000000000000
--- a/android/source/res/drawable-mdpi/lo_icon.png
+++ /dev/null
Binary files differ
diff --git a/android/source/res/drawable-xxxhdpi/decrementindent.png b/android/source/res/drawable-xxxhdpi/decrementindent.png
new file mode 100644
index 000000000000..0995c751d68c
--- /dev/null
+++ b/android/source/res/drawable-xxxhdpi/decrementindent.png
Binary files differ
diff --git a/android/source/res/drawable-xxxhdpi/ic_keyboard_black_24dp.png b/android/source/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png
index ba4d5be6d74d..ba4d5be6d74d 100644
--- a/android/source/res/drawable-xxxhdpi/ic_keyboard_black_24dp.png
+++ b/android/source/res/drawable-xxxhdpi/ic_keyboard_black__24dp.png
Binary files differ
diff --git a/android/source/res/drawable-xxxhdpi/incrementindent.png b/android/source/res/drawable-xxxhdpi/incrementindent.png
new file mode 100644
index 000000000000..619c76bd6b55
--- /dev/null
+++ b/android/source/res/drawable-xxxhdpi/incrementindent.png
Binary files differ
diff --git a/android/source/res/drawable/calc.png b/android/source/res/drawable/calc.png
index 0c0d31444d11..240da6c8966d 100644
--- a/android/source/res/drawable/calc.png
+++ b/android/source/res/drawable/calc.png
Binary files differ
diff --git a/android/source/res/drawable/draw.png b/android/source/res/drawable/draw.png
index b3ee11426a04..8b8436789cc2 100644
--- a/android/source/res/drawable/draw.png
+++ b/android/source/res/drawable/draw.png
Binary files differ
diff --git a/android/source/res/drawable/ic_add_black_24dp.xml b/android/source/res/drawable/ic_add_24dp.xml
index 0258249cc482..7f7afe05c114 100644
--- a/android/source/res/drawable/ic_add_black_24dp.xml
+++ b/android/source/res/drawable/ic_add_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</vector>
diff --git a/android/source/res/drawable/ic_arrow_back_black_24dp.xml b/android/source/res/drawable/ic_arrow_back_24dp.xml
index beafea3959eb..deb00257fb1d 100644
--- a/android/source/res/drawable/ic_arrow_back_black_24dp.xml
+++ b/android/source/res/drawable/ic_arrow_back_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>
diff --git a/android/source/res/drawable/ic_auto_color.xml b/android/source/res/drawable/ic_auto_color.xml
new file mode 100644
index 000000000000..3c68b556ee70
--- /dev/null
+++ b/android/source/res/drawable/ic_auto_color.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,14c0,-4 -6,-10.8 -6,-10.8s-1.33,1.51 -2.73,3.52l8.59,8.59c0.09,-0.42 0.14,-0.86 0.14,-1.31zM17.12,17.12L12.5,12.5 5.27,5.27 4,6.55l3.32,3.32C6.55,11.32 6,12.79 6,14c0,3.31 2.69,6 6,6 1.52,0 2.9,-0.57 3.96,-1.5l2.63,2.63 1.27,-1.27 -2.74,-2.74z"/>
+</vector>
diff --git a/android/source/res/drawable/ic_cloud_black_24dp.xml b/android/source/res/drawable/ic_cloud_black_24dp.xml
deleted file mode 100644
index e0940ca0e7b0..000000000000
--- a/android/source/res/drawable/ic_cloud_black_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96z"/>
-</vector>
diff --git a/android/source/res/drawable/ic_content_copy_black_24dp.xml b/android/source/res/drawable/ic_content_copy_24dp.xml
index 8a894a3bcd73..26f2aefd40a2 100644
--- a/android/source/res/drawable/ic_content_copy_black_24dp.xml
+++ b/android/source/res/drawable/ic_content_copy_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM19,5L8,5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2L21,7c0,-1.1 -0.9,-2 -2,-2zM19,21L8,21L8,7h11v14z"/>
</vector>
diff --git a/android/source/res/drawable/ic_content_cut_black_24dp.xml b/android/source/res/drawable/ic_content_cut_24dp.xml
index 1c0f96a37b42..6a6ba24f2b7f 100644
--- a/android/source/res/drawable/ic_content_cut_black_24dp.xml
+++ b/android/source/res/drawable/ic_content_cut_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M9.64,7.64c0.23,-0.5 0.36,-1.05 0.36,-1.64 0,-2.21 -1.79,-4 -4,-4S2,3.79 2,6s1.79,4 4,4c0.59,0 1.14,-0.13 1.64,-0.36L10,12l-2.36,2.36C7.14,14.13 6.59,14 6,14c-2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4c0,-0.59 -0.13,-1.14 -0.36,-1.64L12,14l7,7h3v-1L9.64,7.64zM6,8c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM6,20c-1.1,0 -2,-0.89 -2,-2s0.9,-2 2,-2 2,0.89 2,2 -0.9,2 -2,2zM12,12.5c-0.28,0 -0.5,-0.22 -0.5,-0.5s0.22,-0.5 0.5,-0.5 0.5,0.22 0.5,0.5 -0.22,0.5 -0.5,0.5zM19,3l-6,6 2,2 7,-7L22,3z"/>
</vector>
diff --git a/android/source/res/drawable/ic_content_paste_black_24dp.xml b/android/source/res/drawable/ic_content_paste_24dp.xml
index a902d9a856a0..e01601364307 100644
--- a/android/source/res/drawable/ic_content_paste_black_24dp.xml
+++ b/android/source/res/drawable/ic_content_paste_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M19,2h-4.18C14.4,0.84 13.3,0 12,0c-1.3,0 -2.4,0.84 -2.82,2L5,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,4c0,-1.1 -0.9,-2 -2,-2zM12,2c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM19,20L5,20L5,4h2v3h10L17,4h2v16z"/>
</vector>
diff --git a/android/source/res/drawable/ic_decrementindent.xml b/android/source/res/drawable/ic_decrementindent.xml
new file mode 100644
index 000000000000..85235d32fd06
--- /dev/null
+++ b/android/source/res/drawable/ic_decrementindent.xml
@@ -0,0 +1,3 @@
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/decrementindent"
+ android:tint="@color/toolbar_foreground"/>
diff --git a/android/source/res/drawable/ic_filter_list_black_24dp.xml b/android/source/res/drawable/ic_filter_list_24dp.xml
index b99b672f4e62..87414cbed6b4 100644
--- a/android/source/res/drawable/ic_filter_list_black_24dp.xml
+++ b/android/source/res/drawable/ic_filter_list_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
</vector>
diff --git a/android/source/res/drawable/ic_folder_black_24dp.xml b/android/source/res/drawable/ic_folder_24dp.xml
index 1a9a16fb1704..0435c89afc5d 100644
--- a/android/source/res/drawable/ic_folder_black_24dp.xml
+++ b/android/source/res/drawable/ic_folder_24dp.xml
@@ -1,5 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
+ <path android:fillColor="@color/toolbar_foreground" android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z"/>
</vector>
diff --git a/android/source/res/drawable/ic_format_clear_black_24dp.xml b/android/source/res/drawable/ic_format_clear_24dp.xml
index 4c903c7163e0..eeb661b8c09a 100644
--- a/android/source/res/drawable/ic_format_clear_black_24dp.xml
+++ b/android/source/res/drawable/ic_format_clear_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M3.27,5L2,6.27l6.97,6.97L6.5,19h3l1.57,-3.66L16.73,21 18,19.73 3.55,5.27 3.27,5zM6,5v0.18L8.82,8h2.4l-0.72,1.68 2.1,2.1L14.21,8H20V5H6z"/>
</vector>
diff --git a/android/source/res/drawable/ic_grid_off_black_24dp.xml b/android/source/res/drawable/ic_grid_off_24dp.xml
index 7cf3c950cc4b..6d5df305e48a 100644
--- a/android/source/res/drawable/ic_grid_off_black_24dp.xml
+++ b/android/source/res/drawable/ic_grid_off_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M8,4v1.45l2,2L10,4h4v4h-3.45l2,2L14,10v1.45l2,2L16,10h4v4h-3.45l2,2L20,16v1.45l2,2L22,4c0,-1.1 -0.9,-2 -2,-2L4.55,2l2,2L8,4zM16,4h4v4h-4L16,4zM1.27,1.27L0,2.55l2,2L2,20c0,1.1 0.9,2 2,2h15.46l2,2 1.27,-1.27L1.27,1.27zM10,12.55L11.45,14L10,14v-1.45zM4,6.55L5.45,8L4,8L4,6.55zM8,20L4,20v-4h4v4zM8,14L4,14v-4h3.45l0.55,0.55L8,14zM14,20h-4v-4h3.45l0.55,0.54L14,20zM16,20v-1.46L17.46,20L16,20z"/>
</vector>
diff --git a/android/source/res/drawable/ic_grid_on_black_24dp.xml b/android/source/res/drawable/ic_grid_on_24dp.xml
index b2ff9e5be07b..3aec5d2840d6 100644
--- a/android/source/res/drawable/ic_grid_on_black_24dp.xml
+++ b/android/source/res/drawable/ic_grid_on_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M20,2L4,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM8,20L4,20v-4h4v4zM8,14L4,14v-4h4v4zM8,8L4,8L4,4h4v4zM14,20h-4v-4h4v4zM14,14h-4v-4h4v4zM14,8h-4L10,4h4v4zM20,20h-4v-4h4v4zM20,14h-4v-4h4v4zM20,8h-4L16,4h4v4z"/>
</vector>
diff --git a/android/source/res/drawable/ic_incrementindent.xml b/android/source/res/drawable/ic_incrementindent.xml
new file mode 100644
index 000000000000..3bee99911ec1
--- /dev/null
+++ b/android/source/res/drawable/ic_incrementindent.xml
@@ -0,0 +1,3 @@
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/incrementindent"
+ android:tint="@color/toolbar_foreground"/>
diff --git a/android/source/res/drawable/ic_insert_drive_file_black_24dp.xml b/android/source/res/drawable/ic_insert_drive_file_black_24dp.xml
deleted file mode 100644
index aaeb289d7060..000000000000
--- a/android/source/res/drawable/ic_insert_drive_file_black_24dp.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:width="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0" >
- <path android:fillColor="#FF000000" android:pathData="M6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6L6,2zM13,9L13,3.5L18.5,9L13,9z"/>
-</vector>
diff --git a/android/source/res/drawable/ic_keyboard_backspace_black_24dp.xml b/android/source/res/drawable/ic_keyboard_backspace_black_24dp.xml
deleted file mode 100644
index 827cde0056cd..000000000000
--- a/android/source/res/drawable/ic_keyboard_backspace_black_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M21,11H6.83l3.58,-3.59L9,6l-6,6 6,6 1.41,-1.41L6.83,13H21z"/>
-</vector>
diff --git a/android/source/res/drawable/ic_line.xml b/android/source/res/drawable/ic_line.xml
index 639ba2dbf690..ae33c2929c94 100644
--- a/android/source/res/drawable/ic_line.xml
+++ b/android/source/res/drawable/ic_line.xml
@@ -7,6 +7,6 @@
android:pathData="M4,11h16v2h-16z"
android:fillAlpha="1"
android:strokeColor="#00000000"
- android:fillColor="#4d4d4d"
+ android:fillColor="@color/toolbar_foreground"
android:strokeWidth="2"/>
</vector>
diff --git a/android/source/res/drawable/ic_menu_back.png b/android/source/res/drawable/ic_menu_back.png
deleted file mode 100644
index d3191caffd13..000000000000
--- a/android/source/res/drawable/ic_menu_back.png
+++ /dev/null
Binary files differ
diff --git a/android/source/res/drawable/ic_rect.xml b/android/source/res/drawable/ic_rect.xml
index 241759ff00c3..ac6db359f56e 100644
--- a/android/source/res/drawable/ic_rect.xml
+++ b/android/source/res/drawable/ic_rect.xml
@@ -7,7 +7,7 @@
android:pathData="M4,6h16v12h-16z"
android:fillAlpha="0.99"
android:strokeColor="#00000000"
- android:fillColor="#4d4d4d"
+ android:fillColor="@color/toolbar_foreground"
android:strokeWidth="4"
android:strokeAlpha="0.99"/>
</vector>
diff --git a/android/source/res/drawable/ic_sd_card_black_24dp.xml b/android/source/res/drawable/ic_sd_card_black_24dp.xml
deleted file mode 100644
index f9ad72d482db..000000000000
--- a/android/source/res/drawable/ic_sd_card_black_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M18,2h-8L4.02,8 4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM12,8h-2L10,4h2v4zM15,8h-2L13,4h2v4zM18,8h-2L16,4h2v4z"/>
-</vector>
diff --git a/android/source/res/drawable/ic_settings_black_24dp.xml b/android/source/res/drawable/ic_settings_24dp.xml
index ace746c40eed..990ea6fb9c33 100644
--- a/android/source/res/drawable/ic_settings_black_24dp.xml
+++ b/android/source/res/drawable/ic_settings_24dp.xml
@@ -4,6 +4,6 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
- android:fillColor="#FF000000"
+ android:fillColor="@color/toolbar_foreground"
android:pathData="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
</vector>
diff --git a/android/source/res/drawable/ic_sort_black_24dp.xml b/android/source/res/drawable/ic_sort_24dp.xml
index d582deea67ec..7f5f2d4e8702 100644
--- a/android/source/res/drawable/ic_sort_black_24dp.xml
+++ b/android/source/res/drawable/ic_sort_24dp.xml
@@ -9,5 +9,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
- <path android:fillColor="#FF000000" android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
+ <path android:fillColor="@color/toolbar_foreground" android:pathData="M3,18h6v-2L3,16v2zM3,6v2h18L21,6L3,6zM3,13h12v-2L3,11v2z"/>
</vector>
diff --git a/android/source/res/drawable/ic_storage_black_24dp.xml b/android/source/res/drawable/ic_storage_black_24dp.xml
deleted file mode 100644
index 53c595cd7d1c..000000000000
--- a/android/source/res/drawable/ic_storage_black_24dp.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:fillColor="#FF000000"
- android:pathData="M2,20h20v-4L2,16v4zM4,17h2v2L4,19v-2zM2,4v4h20L22,4L2,4zM6,7L4,7L4,5h2v2zM2,14h20v-4L2,10v4zM4,11h2v2L4,13v-2z"/>
-</vector>
diff --git a/android/source/res/drawable/ic_usb_black_24dp.xml b/android/source/res/drawable/ic_usb_black_24dp.xml
deleted file mode 100644
index d9b39bac1a86..000000000000
--- a/android/source/res/drawable/ic_usb_black_24dp.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:width="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0" >
- <path android:fillColor="#FF000000" android:pathData="M15,7v4h1v2h-3V5h2l-3,-4 -3,4h2v8H8v-2.07c0.7,-0.37 1.2,-1.08 1.2,-1.93 0,-1.21 -0.99,-2.2 -2.2,-2.2 -1.21,0 -2.2,0.99 -2.2,2.2 0,0.85 0.5,1.56 1.2,1.93V13c0,1.11 0.89,2 2,2h3v3.05c-0.71,0.37 -1.2,1.1 -1.2,1.95 0,1.22 0.99,2.2 2.2,2.2 1.21,0 2.2,-0.98 2.2,-2.2 0,-0.85 -0.49,-1.58 -1.2,-1.95V15h3c1.11,0 2,-0.89 2,-2v-2h1V7h-4z"/>
-</vector>
diff --git a/android/source/res/drawable/impress.png b/android/source/res/drawable/impress.png
index 5909f05bf089..2de82d6bd42b 100644
--- a/android/source/res/drawable/impress.png
+++ b/android/source/res/drawable/impress.png
Binary files differ
diff --git a/android/source/res/drawable/label_background.xml b/android/source/res/drawable/label_background.xml
index 1e097857537a..2727c7d9ab0b 100644
--- a/android/source/res/drawable/label_background.xml
+++ b/android/source/res/drawable/label_background.xml
@@ -2,8 +2,8 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
- <solid android:color="@color/background_normal" />
+ <solid android:color="@color/background_floating" />
<corners android:radius="5dp" />
</shape>
</item>
-</selector> \ No newline at end of file
+</selector>
diff --git a/android/source/res/drawable/writer.png b/android/source/res/drawable/writer.png
index 8a4e21e47174..6cc9e8483033 100644
--- a/android/source/res/drawable/writer.png
+++ b/android/source/res/drawable/writer.png
Binary files differ
diff --git a/android/source/res/layout/about.xml b/android/source/res/layout/about.xml
index 8968c00d2695..f37482b82a0c 100644
--- a/android/source/res/layout/about.xml
+++ b/android/source/res/layout/about.xml
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -14,8 +15,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
- android:text="@string/app_version"
- android:textSize="18sp"/>
+ android:textSize="18sp"
+ tools:text="Version: x.x.x.x\nBuild ID: 000000000000" />
<TextView
android:id="@+id/about_description"
@@ -39,7 +40,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
- android:text="@string/app_vendor"
- android:textSize="18sp"/>
+ android:textSize="18sp"
+ tools:text="@string/app_vendor" />
</LinearLayout>
</ScrollView>
diff --git a/android/source/res/layout/activity_directory_browser.xml b/android/source/res/layout/activity_directory_browser.xml
deleted file mode 100644
index b03c6bbb1224..000000000000
--- a/android/source/res/layout/activity_directory_browser.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/fragment_container"
- android:layout_width="match_parent" android:layout_height="match_parent">
-
-</FrameLayout> \ No newline at end of file
diff --git a/android/source/res/layout/activity_document_browser.xml b/android/source/res/layout/activity_document_browser.xml
index 8e17a3e1624f..72b6e42b29b2 100644
--- a/android/source/res/layout/activity_document_browser.xml
+++ b/android/source/res/layout/activity_document_browser.xml
@@ -6,7 +6,7 @@
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
-->
-<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@@ -14,12 +14,11 @@
android:orientation="vertical">
<!-- The toolbar -->
- <android.support.v7.widget.Toolbar
+ <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:elevation="3dp"
- android:background="@color/toolbar_background"
app:theme="@style/LibreOfficeTheme.Toolbar"
tools:theme="@style/LibreOfficeTheme.Toolbar"
app:popupTheme="@style/LibreOfficeTheme"
@@ -30,10 +29,10 @@
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent">
- </android.support.v7.widget.Toolbar>
+ </com.google.android.material.appbar.MaterialToolbar>
- <android.support.v4.widget.DrawerLayout
+ <androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="0dp"
android:layout_height="0dp"
@@ -47,7 +46,7 @@
app:layout_constraintLeft_toLeftOf="parent">
<!-- The content -->
- <android.support.v4.widget.NestedScrollView
+ <androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -59,78 +58,62 @@
android:showDividers="middle">
<TextView
+ android:id="@+id/header_browser"
android:layout_width="match_parent"
- android:layout_height="48dp"
- android:id="@+id/header_recents"
- android:text="@string/title_recents"
+ android:layout_height="wrap_content"
android:gravity="center_vertical"
- android:textSize="14sp"
android:padding="16dp"
+ android:text="@string/title_browser"
+ android:textSize="14sp"
android:textStyle="bold" />
- <!--Recent files-->
- <android.support.v7.widget.RecyclerView
- android:id="@+id/list_recent"
+ <Button
+ android:id="@+id/open_file_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:layout_marginBottom="8dp" />
+ android:layout_weight="1"
+ android:gravity="center_vertical"
+ android:text="@string/select_file_to_open"
+ android:textSize="14dp"
+ app:drawableLeftCompat="@drawable/ic_folder_48dp" />
<TextView
android:layout_width="match_parent"
- android:layout_height="48dp"
- android:id="@+id/header_browser"
- android:text="@string/title_browser"
+ android:layout_height="wrap_content"
+ android:id="@+id/header_recents"
+ android:text="@string/title_recents"
android:gravity="center_vertical"
android:textSize="14sp"
android:padding="16dp"
android:textStyle="bold" />
- <TextView
+ <!--Recent files-->
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/list_recent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textSize="14sp"
- android:padding="7dp"
- android:id="@+id/text_directory_path"
- android:background="@color/background_normal"
- />
-
-
- <!--Document browser-->
- <android.support.v7.widget.RecyclerView
- android:id="@+id/file_recycler_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/background_normal"
- android:orientation="vertical" />
+ android:layout_marginTop="8dp"
+ android:layout_marginBottom="8dp" />
</LinearLayout>
- </android.support.v4.widget.NestedScrollView>
+ </androidx.core.widget.NestedScrollView>
<!-- The navigation drawer -->
- <android.support.design.widget.NavigationView
- android:id="@+id/navigation_drawer"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_gravity="start"
- android:background="@color/background_normal"
- app:menu="@menu/navigation_menu"
- android:theme="@style/LibreOfficeTheme.NavigationView" />
- </android.support.v4.widget.DrawerLayout>
+ </androidx.drawerlayout.widget.DrawerLayout>
- <android.support.design.widget.FloatingActionButton
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/editFAB"
+ android:contentDescription="@string/create_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
- android:visibility="invisible"
- app:backgroundTint="@color/background_normal"
+ app:backgroundTint="@color/background_floating"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
- app:srcCompat="@drawable/ic_add_black_24dp"
+ app:srcCompat="@drawable/ic_add_24dp"
app:useCompatPadding="true" />
<LinearLayout
@@ -151,14 +134,14 @@
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:text="@string/new_textdocument" />
- <android.support.design.widget.FloatingActionButton
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/newWriterFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/new_doc_fab_tweak_bottom"
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:clickable="true"
- app:backgroundTint="@color/background_normal"
+ app:backgroundTint="@color/background_floating"
app:fabSize="mini"
app:srcCompat="@drawable/writer"
app:useCompatPadding="true" />
@@ -183,14 +166,14 @@
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:text="@string/new_presentation" />
- <android.support.design.widget.FloatingActionButton
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/newImpressFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/new_doc_fab_tweak_bottom"
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:clickable="true"
- app:backgroundTint="@color/background_normal"
+ app:backgroundTint="@color/background_floating"
app:fabSize="mini"
app:srcCompat="@drawable/impress"
app:useCompatPadding="true" />
@@ -215,14 +198,14 @@
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:text="@string/new_spreadsheet" />
- <android.support.design.widget.FloatingActionButton
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/newCalcFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/new_doc_fab_tweak_bottom"
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:clickable="true"
- app:backgroundTint="@color/background_normal"
+ app:backgroundTint="@color/background_floating"
app:fabSize="mini"
app:srcCompat="@drawable/calc"
app:useCompatPadding="true" />
@@ -247,18 +230,18 @@
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:text="@string/new_drawing" />
- <android.support.design.widget.FloatingActionButton
+ <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/newDrawFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/new_doc_fab_tweak_bottom"
android:layout_marginTop="@dimen/new_doc_fab_tweak_top"
android:clickable="true"
- app:backgroundTint="@color/background_normal"
+ app:backgroundTint="@color/background_floating"
app:fabSize="mini"
app:srcCompat="@drawable/draw"
app:useCompatPadding="true" />
</LinearLayout>
-</android.support.constraint.ConstraintLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/android/source/res/layout/activity_main.xml b/android/source/res/layout/activity_main.xml
index c2528023d0f8..e503cb90f0eb 100644
--- a/android/source/res/layout/activity_main.xml
+++ b/android/source/res/layout/activity_main.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.v4.widget.DrawerLayout android:id="@+id/drawer_layout"
+<androidx.drawerlayout.widget.DrawerLayout android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
@@ -8,7 +8,7 @@
android:background="#fff"
tools:context=".LibreOfficeMainActivity">
- <android.support.design.widget.CoordinatorLayout
+ <androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -18,44 +18,46 @@
android:layout_height="match_parent"
android:orientation="vertical">
- <android.support.design.widget.AppBarLayout
+ <com.google.android.material.appbar.AppBarLayout
android:id="@+id/appBar"
android:layout_width="match_parent"
android:layout_height="wrap_content">
- <android.support.v7.widget.Toolbar
+ <com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:elevation="3dp"
- android:background="@color/toolbar_background"
app:theme="@style/LibreOfficeTheme.Toolbar"
tools:theme="@style/LibreOfficeTheme.Toolbar"
app:popupTheme="@style/LibreOfficeTheme" />
- </android.support.design.widget.AppBarLayout>
+ </com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:background="@color/background_floating">
<EditText
android:id="@+id/calc_address"
android:layout_width="@dimen/calc_address_bar_width"
- android:layout_height="@dimen/calc_toolbar_height"
+ android:layout_height="wrap_content"
android:layout_weight="0"
android:inputType="textNoSuggestions"
android:imeOptions="actionDone|actionGo"
- android:visibility="gone"/>
+ android:visibility="gone"
+ android:importantForAutofill="no" />
<EditText
android:id="@+id/calc_formula"
android:layout_width="0dp"
- android:layout_height="@dimen/calc_toolbar_height"
+ android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"
android:imeOptions="actionDone|actionGo"
- android:visibility="gone"/>
+ android:visibility="gone"
+ android:importantForAutofill="no" />
</LinearLayout>
@@ -133,7 +135,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- </android.support.design.widget.CoordinatorLayout>
+ </androidx.coordinatorlayout.widget.CoordinatorLayout>
<ListView
android:id="@+id/left_drawer"
@@ -143,4 +145,4 @@
android:background="#9FFF"
android:choiceMode="singleChoice"/>
-</android.support.v4.widget.DrawerLayout>
+</androidx.drawerlayout.widget.DrawerLayout>
diff --git a/android/source/res/layout/file_explorer_grid_item.xml b/android/source/res/layout/file_explorer_grid_item.xml
deleted file mode 100644
index e64fdc23a6a7..000000000000
--- a/android/source/res/layout/file_explorer_grid_item.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- This file is part of the LibreOffice project.
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="4dp"
- android:paddingBottom="4dp"
- android:orientation="vertical" >
-
- <ImageView
- android:id="@+id/file_item_icon"
- tools:src="@drawable/ic_folder_black_24dp"
- tools:tint="@color/text_color_secondary"
- android:layout_width="100dp"
- android:layout_height="100dp"
- android:scaleType="fitStart"
- android:layout_gravity="center"
- android:contentDescription="@string/file_icon_desc" >
- </ImageView>
-
- <TextView
- android:id="@+id/file_item_name"
- tools:text="file or dirname"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingLeft="10dp"
- android:paddingRight="10dp"
- android:paddingTop="10dp"
- android:layout_gravity="center"
- android:textSize="15sp"
- android:textStyle="bold"
- android:textColor="@android:color/secondary_text_light"
- android:maxLines="2">
- </TextView>
-
-</LinearLayout>
diff --git a/android/source/res/layout/file_grid.xml b/android/source/res/layout/file_grid.xml
deleted file mode 100644
index 1885bd34ed6a..000000000000
--- a/android/source/res/layout/file_grid.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- This file is part of the LibreOffice project.
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <GridView
- android:id="@+id/file_explorer_grid_view"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:columnWidth="120dp"
- android:numColumns="auto_fit"
- android:verticalSpacing="10dp"
- android:horizontalSpacing="10dp"
- android:stretchMode="columnWidth"
- android:gravity="center">
- </GridView>
-
-</LinearLayout>
diff --git a/android/source/res/layout/file_list.xml b/android/source/res/layout/file_list.xml
deleted file mode 100644
index 48dfb1e31267..000000000000
--- a/android/source/res/layout/file_list.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- This file is part of the LibreOffice project.
-
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
-
- <ListView
- android:id="@+id/file_explorer_list_view"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- </ListView>
-
-</LinearLayout>
diff --git a/android/source/res/layout/file_list_item.xml b/android/source/res/layout/file_list_item.xml
deleted file mode 100644
index 518885d4b296..000000000000
--- a/android/source/res/layout/file_list_item.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- This file is part of the LibreOffice project.
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
- -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:orientation="horizontal"
- android:layout_marginStart="@dimen/list_item_margin"
- android:layout_marginLeft="@dimen/list_item_margin"
- android:layout_marginEnd="@dimen/list_item_margin"
- android:layout_marginRight="@dimen/list_item_margin">
- <ImageView
- android:id="@+id/file_item_icon"
- tools:src="@drawable/ic_folder_black_24dp"
- tools:tint="@color/text_color_secondary"
- android:layout_height="match_parent"
- android:layout_width="@dimen/file_icon_width"
- android:layout_marginEnd="@dimen/file_icon_margin_end"
- android:layout_marginRight="@dimen/file_icon_margin_end"
- android:layout_gravity="center"
- android:contentDescription="@string/file_icon_desc" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:orientation="horizontal">
- <TextView
- android:id="@+id/file_item_name"
- tools:text="file or dirname"
- style="@style/ListItemText"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="2"
- android:ellipsize="end"
- android:maxLines="1"/>
- <TextView
- android:id="@+id/file_item_size"
- tools:text="filesize"
- style="@style/ListItemText"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="1" />
- <TextView
- android:id="@+id/file_item_date"
- tools:text="date/time"
- style="@style/ListItemText"
- android:layout_height="match_parent"
- android:layout_width="0dp"
- android:layout_weight="2"
- android:ellipsize="end"
- android:gravity="end"
- android:maxLines="1"/>
- </LinearLayout>
-</LinearLayout>
diff --git a/android/source/res/layout/fragment_directory_browser.xml b/android/source/res/layout/fragment_directory_browser.xml
deleted file mode 100644
index 37a61fa3518c..000000000000
--- a/android/source/res/layout/fragment_directory_browser.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical" android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#FFFFFF">
-
- <LinearLayout
- android:id="@+id/browser_header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/up_image"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:src="@drawable/ic_menu_back"
- android:scaleType="fitCenter"
- android:adjustViewBounds="true"
- android:contentDescription="@string/up_description"/>
-
- <EditText
- android:id="@+id/directory_header"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:maxLines="1"
- android:scrollHorizontally="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:inputType="text"/>
-
- <Button
- android:id="@+id/directory_search_button"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:text="@string/search_label"/>
-
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/browser_footer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:layout_alignParentBottom="true">
-
- <Button
- android:id="@+id/cancel_button"
- android:layout_height="wrap_content"
- android:layout_width="0dp"
- android:layout_weight="1"
- android:text="@string/cancel_label"/>
-
- <Button
- android:id="@+id/confirm_button"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:text="@string/confirm_label"/>
- </LinearLayout>
-
- <ListView
- android:id="@+id/directory_list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/browser_header"
- android:layout_above="@id/browser_footer">
- </ListView>
-
-
-</RelativeLayout> \ No newline at end of file
diff --git a/android/source/res/layout/item_recent_files.xml b/android/source/res/layout/item_recent_files.xml
index b374ba56f04f..f13839b44b73 100644
--- a/android/source/res/layout/item_recent_files.xml
+++ b/android/source/res/layout/item_recent_files.xml
@@ -11,7 +11,6 @@
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
- android:background="?android:attr/selectableItemBackground"
android:layout_marginStart="@dimen/list_item_margin"
android:layout_marginLeft="@dimen/list_item_margin"
android:layout_marginEnd="@dimen/list_item_margin"
diff --git a/android/source/res/layout/number_picker.xml b/android/source/res/layout/number_picker.xml
index 51463926c70f..32eea0e80a84 100644
--- a/android/source/res/layout/number_picker.xml
+++ b/android/source/res/layout/number_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -127,4 +127,4 @@
android:background="@drawable/image_button_background"
app:layout_constraintEnd_toEndOf="@+id/numberpickerLayout"
app:layout_constraintTop_toBottomOf="@+id/number_picker_rows_positive" />
-</android.support.constraint.ConstraintLayout> \ No newline at end of file
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/android/source/res/layout/toolbar_bottom.xml b/android/source/res/layout/toolbar_bottom.xml
index f4b3f3c5f8cc..172b215f5a1c 100644
--- a/android/source/res/layout/toolbar_bottom.xml
+++ b/android/source/res/layout/toolbar_bottom.xml
@@ -7,13 +7,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- android:background="@color/toolbar_background"
+ android:background="?attr/colorPrimary"
android:elevation="3dp"
android:orientation="vertical"
app:popupTheme="@style/LibreOfficeTheme.Toolbar"
app:theme="@style/LibreOfficeTheme.Toolbar"
tools:showIn="@layout/activity_main"
- app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
+ app:layout_behavior="@string/bottom_sheet_behavior"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp">
@@ -115,7 +115,7 @@
android:background="@drawable/image_button_background"
android:paddingBottom="12dp"
android:paddingTop="12dp"
- app:srcCompat="@drawable/ic_format_clear_black_24dp" />
+ app:srcCompat="@drawable/ic_format_clear_24dp" />
</LinearLayout>
@@ -269,6 +269,27 @@
android:paddingBottom="12dp"
android:paddingTop="12dp"
android:src="@drawable/ic_format_bullets" />
+
+ <ImageButton
+ android:id="@+id/button_increaseIndent"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="0.25"
+ android:background="@drawable/image_button_background"
+ android:paddingBottom="12dp"
+ android:paddingTop="12dp"
+ android:src="@drawable/ic_incrementindent" />
+
+ <ImageButton
+ android:id="@+id/button_decreaseIndent"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="0.25"
+ android:background="@drawable/image_button_background"
+ android:paddingBottom="12dp"
+ android:paddingTop="12dp"
+ android:src="@drawable/ic_decrementindent" />
+
</LinearLayout>
</LinearLayout>
@@ -319,7 +340,7 @@
android:background="@drawable/image_button_background"
android:paddingBottom="12dp"
android:paddingTop="12dp"
- app:srcCompat="@drawable/ic_folder_black_24dp" />
+ app:srcCompat="@drawable/ic_folder_24dp" />
<ImageButton
android:id="@+id/button_insert_table"
@@ -329,7 +350,7 @@
android:background="@drawable/image_button_background"
android:paddingBottom="12dp"
android:paddingTop="12dp"
- app:srcCompat="@drawable/ic_grid_on_black_24dp" />
+ app:srcCompat="@drawable/ic_grid_on_24dp" />
<ImageButton
android:id="@+id/button_delete_table"
@@ -339,7 +360,7 @@
android:background="@drawable/image_button_background"
android:paddingBottom="12dp"
android:paddingTop="12dp"
- app:srcCompat="@drawable/ic_grid_off_black_24dp" />
+ app:srcCompat="@drawable/ic_grid_off_24dp" />
</LinearLayout>
</ScrollView>
</LinearLayout>
@@ -370,7 +391,7 @@
android:paddingTop="12dp"
android:textSize="14sp"
android:gravity="center_vertical"
- android:textColor="@color/fontBlack"
+ android:textColor="?android:attr/textColorPrimary"
android:layout_alignParentLeft="true"
/>
@@ -399,7 +420,7 @@
android:paddingTop="12dp"
android:textSize="14sp"
android:gravity="center_vertical"
- android:textColor="@color/fontBlack"
+ android:textColor="?android:attr/textColorPrimary"
android:layout_alignParentLeft="true"
/>
@@ -445,7 +466,8 @@
android:layout_weight="0.6"
android:background="@drawable/image_button_background"
android:padding="10dp"
- android:src="@drawable/ic_search_direction_down" />
+ android:src="@drawable/ic_search_direction_down"
+ android:contentDescription="@string/search_find_next" />
<ImageButton
android:id="@+id/button_search_up"
@@ -454,7 +476,8 @@
android:layout_weight="0.6"
android:background="@drawable/image_button_background"
android:padding="10dp"
- android:src="@drawable/ic_search_direction_up" />
+ android:src="@drawable/ic_search_direction_up"
+ android:contentDescription="@string/search_find_previous" />
</LinearLayout>
<LinearLayout
@@ -491,7 +514,7 @@
android:layout_height="wrap_content"
android:background="@drawable/image_button_background"
android:padding="10dp"
- app:srcCompat="@drawable/ic_filter_list_black_24dp" />
+ app:srcCompat="@drawable/ic_filter_list_24dp" />
<ImageButton
android:id="@+id/button_send_UNO_commands_clear"
@@ -543,7 +566,7 @@
android:layout_height="wrap_content"
android:background="@drawable/image_button_background"
android:padding="10dp"
- app:srcCompat="@drawable/ic_add_black_24dp" />
+ app:srcCompat="@drawable/ic_add_24dp" />
</LinearLayout>
diff --git a/android/source/res/layout/toolbar_color_picker.xml b/android/source/res/layout/toolbar_color_picker.xml
index 9393259123be..0969d0e52e3d 100644
--- a/android/source/res/layout/toolbar_color_picker.xml
+++ b/android/source/res/layout/toolbar_color_picker.xml
@@ -6,13 +6,13 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- android:background="@color/toolbar_background"
+ android:background="?attr/colorPrimary"
android:elevation="3dp"
android:orientation="vertical"
app:popupTheme="@style/LibreOfficeTheme.Toolbar"
app:theme="@style/LibreOfficeTheme.Toolbar"
tools:showIn="@layout/activity_main"
- app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
+ app:layout_behavior="@string/bottom_sheet_behavior"
app:behavior_hideable="true"
app:behavior_peekHeight="0dp">
@@ -21,23 +21,41 @@
android:layout_height="wrap_content"
android:padding="10dp"
android:orientation="vertical">
- <ImageButton
- android:id="@+id/button_go_back_color_picker"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- app:srcCompat="@drawable/ic_arrow_back_black_24dp"
- android:background="@drawable/image_button_background"
- android:layout_marginBottom="10dp"/>
- <android.support.v7.widget.RecyclerView
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <ImageButton
+ android:id="@+id/button_go_back_color_picker"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:background="@drawable/image_button_background"
+ app:srcCompat="@drawable/ic_arrow_back_24dp" />
+
+ <Button
+ android:id="@+id/button_auto_color"
+ android:layout_alignParentRight="true"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ android:background="@drawable/image_button_background"
+ android:text="@string/automatic"
+ app:drawableLeftCompat="@drawable/ic_auto_color" />
+
+ </RelativeLayout>
+
+ <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/fontColorView"
>
- </android.support.v7.widget.RecyclerView>
+ </androidx.recyclerview.widget.RecyclerView>
- <android.support.v7.widget.RecyclerView
+ <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fontColorViewSub"
@@ -45,11 +63,11 @@
android:layout_below="@id/fontColorView"
android:layout_alignParentBottom="true">
- </android.support.v7.widget.RecyclerView>
+ </androidx.recyclerview.widget.RecyclerView>
</LinearLayout>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/android/source/res/menu/context_menu.xml b/android/source/res/menu/context_menu.xml
deleted file mode 100644
index 43824875d867..000000000000
--- a/android/source/res/menu/context_menu.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:id="@+id/context_menu_open"
- android:title="@string/open"/>
- <item android:id="@+id/context_menu_share"
- android:title="@string/share"/>
-</menu>
diff --git a/android/source/res/menu/main.xml b/android/source/res/menu/main.xml
index 2c97b3201b9e..cbca33aa4a81 100644
--- a/android/source/res/menu/main.xml
+++ b/android/source/res/menu/main.xml
@@ -31,10 +31,25 @@
android:orderInCategory="100"
app:showAsAction="always"/>
+ <item android:id="@+id/action_UNO_commands"
+ android:title="@string/action_UNO_commands"
+ android:orderInCategory="100" />
+
+ </group>
+
+ <group android:id="@+id/group_misc_actions"
+ tools:visible="true"
+ android:visible="false">
<item android:id="@+id/action_save"
android:title="@string/action_save"
- android:orderInCategory="100" />
+ android:orderInCategory="100"
+ android:visible="true" />
+
+ <item android:id="@+id/action_save_as"
+ android:title="@string/action_save_as"
+ android:orderInCategory="100"
+ android:visible="true" />
<item android:id="@+id/action_exportToPDF"
android:title="@string/action_exportToPDF"
@@ -47,9 +62,6 @@
android:orderInCategory="100"
android:visible="true" />
- <item android:id="@+id/action_UNO_commands"
- android:title="@string/action_UNO_commands"
- android:orderInCategory="100" />
</group>
<group android:id="@+id/group_spreadsheet_options"
@@ -98,25 +110,25 @@
<item android:id="@+id/action_back"
android:title="@string/action_back"
app:showAsAction="always"
- android:icon="@drawable/ic_arrow_back_black_24dp"
+ android:icon="@drawable/ic_arrow_back_24dp"
android:orderInCategory="1"/>
<item android:id="@+id/action_copy"
android:title="@string/action_copy"
app:showAsAction="always"
- android:icon="@drawable/ic_content_copy_black_24dp"
+ android:icon="@drawable/ic_content_copy_24dp"
android:orderInCategory="2"/>
<item android:id="@+id/action_cut"
android:title="@string/action_cut"
app:showAsAction="always"
- android:icon="@drawable/ic_content_cut_black_24dp"
+ android:icon="@drawable/ic_content_cut_24dp"
android:orderInCategory="3"/>
<item android:id="@+id/action_paste"
android:title="@string/action_paste"
app:showAsAction="always"
- android:icon="@drawable/ic_content_paste_black_24dp"
+ android:icon="@drawable/ic_content_paste_24dp"
android:orderInCategory="4"/>
</group>
diff --git a/android/source/res/menu/navigation_menu.xml b/android/source/res/menu/navigation_menu.xml
deleted file mode 100644
index db680a9a1b8c..000000000000
--- a/android/source/res/menu/navigation_menu.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <group
- android:checkableBehavior="single"
- android:id="@+id/group_providers">
-
- <item android:id="@+id/menu_provider_documents"
- android:title="@string/local_documents"
- android:icon="@drawable/ic_folder_black_24dp" />
-
- <item android:id="@+id/menu_provider_filesystem"
- android:title="@string/local_file_system"
- android:icon="@drawable/ic_storage_black_24dp"/>
-
- <item android:id="@+id/menu_provider_extsd"
- android:title="@string/external_sd_file_system"
- android:icon="@drawable/ic_sd_card_black_24dp"/>
-
- <item android:id="@+id/menu_provider_otg"
- android:title="@string/otg_file_system"
- android:icon="@drawable/ic_usb_black_24dp"/>
-
- <item android:id="@+id/menu_provider_owncloud"
- android:title="@string/owncloud"
- android:icon="@drawable/ic_cloud_black_24dp"/>
-
-
- </group>
-
- <group android:orderInCategory="100">
- <item android:id="@+id/menu_storage_preferences"
- android:title="@string/storage_provider_settings"
- android:icon="@drawable/ic_settings_black_24dp"/>
- </group>
-</menu>
diff --git a/android/source/res/menu/view_menu.xml b/android/source/res/menu/view_menu.xml
index 67f059647989..a40bdf5802c9 100644
--- a/android/source/res/menu/view_menu.xml
+++ b/android/source/res/menu/view_menu.xml
@@ -2,60 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
- <item
- android:id="@+id/menu_filter"
- android:title="@string/filter"
- android:icon="@drawable/ic_filter_list_black_24dp"
- app:showAsAction="ifRoom">
- <menu>
- <group
- android:checkableBehavior="single">
- <item
- android:id="@+id/menu_filter_everything"
- android:title="@string/filter_everything" />
- <item
- android:id="@+id/menu_filter_documents"
- android:title="@string/filter_documents" />
- <item
- android:id="@+id/menu_filter_spreadsheets"
- android:title="@string/filter_spreadsheets" />
- <item
- android:id="@+id/menu_filter_presentations"
- android:title="@string/filter_presentations" />
- <item
- android:id="@+id/menu_filter_drawings"
- android:title="@string/filter_drawings" />
- </group>
- </menu>
- </item>
-
- <item
- android:id="@+id/menu_sort"
- android:title="@string/sort"
- android:icon="@drawable/ic_sort_black_24dp"
- app:showAsAction="ifRoom">
- <menu>
- <group android:checkableBehavior="single">
- <item android:id="@+id/menu_sort_size_asc"
- android:title="@string/sort_smallest" />
-
- <item android:id="@+id/menu_sort_size_desc"
- android:title="@string/sort_largest" />
-
- <item android:id="@+id/menu_sort_az"
- android:title="@string/sort_az"/>
-
- <item android:id="@+id/menu_sort_za"
- android:title="@string/sort_za"/>
-
- <item android:id="@+id/menu_sort_modified_newest"
- android:title="@string/sort_newest"/>
-
- <item android:id="@+id/menu_sort_modified_oldest"
- android:title="@string/sort_oldest"/>
- </group>
- </menu>
- </item>
<item android:id="@+id/action_settings"
android:title="@string/action_settings"
android:orderInCategory="100"/>
diff --git a/android/source/res/mipmap-hdpi/ic_launcher.png b/android/source/res/mipmap-hdpi/ic_launcher.png
index f8b74553e385..0765a1e0108e 100644
--- a/android/source/res/mipmap-hdpi/ic_launcher.png
+++ b/android/source/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/android/source/res/mipmap-mdpi/ic_launcher.png b/android/source/res/mipmap-mdpi/ic_launcher.png
index fa68d30f003a..dcc03ff1fb2c 100644
--- a/android/source/res/mipmap-mdpi/ic_launcher.png
+++ b/android/source/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/android/source/res/mipmap-xhdpi/ic_launcher.png b/android/source/res/mipmap-xhdpi/ic_launcher.png
index 12069c7e8ac5..d8fb1d912633 100644
--- a/android/source/res/mipmap-xhdpi/ic_launcher.png
+++ b/android/source/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/android/source/res/mipmap-xxhdpi/ic_launcher.png b/android/source/res/mipmap-xxhdpi/ic_launcher.png
index a00a40dbe1de..7b9a8029aa40 100644
--- a/android/source/res/mipmap-xxhdpi/ic_launcher.png
+++ b/android/source/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/android/source/res/mipmap-xxxhdpi/ic_launcher.png b/android/source/res/mipmap-xxxhdpi/ic_launcher.png
index ef7067cbd2a3..86d268ede8ef 100644
--- a/android/source/res/mipmap-xxxhdpi/ic_launcher.png
+++ b/android/source/res/mipmap-xxxhdpi/ic_launcher.png
Binary files differ
diff --git a/android/source/res/values-ab/strings.xml b/android/source/res/values-ab/strings.xml
new file mode 100644
index 000000000000..a6b3daec9354
--- /dev/null
+++ b/android/source/res/values-ab/strings.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources></resources> \ No newline at end of file
diff --git a/android/source/res/values-ast/strings.xml b/android/source/res/values-ast/strings.xml
new file mode 100644
index 000000000000..27e9d06bd131
--- /dev/null
+++ b/android/source/res/values-ast/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="about_license">Amosar la llicencia</string>
+ <string name="new_textdocument">Documentu de testu nuevu</string>
+ <string name="new_drawing">Dibuxu nuevu</string>
+ <string name="default_document_name">ensin títulu</string>
+ <string name="select_file_to_open">Esbilla\'l ficheru que quies abrir</string>
+ <string name="title_recents">Ficheros recién</string>
+ <string name="title_browser">Tolos ficheros</string>
+ <string name="action_settings">Axustes</string>
+ <string name="action_keyboard">Amosar el tecláu</string>
+ <string name="action_redo">Refacer</string>
+ <string name="no_save_document">NON</string>
+ <string name="calc_delete">Desaniciar</string>
+ <string name="calc_hide">Anubrir</string>
+ <string name="calc_show">Amosar</string>
+ <string name="sheet">Fueya</string>
+ <string name="readonly_file">Esti ficheru ye namái de llectura.</string>
+ <string name="new_presentation">Presentación nueva</string>
+ <string name="new_spreadsheet">Fueya de cálculu nueva</string>
+ <string name="action_about">Tocante a</string>
+ <string name="action_save">Guardar</string>
+ <string name="action_search">Guetar</string>
+ <string name="action_undo">Desfacer</string>
+ <string name="page">Páxina</string>
+ <string name="app_name_settings">Configuración del visor del LibreOffice</string>
+ <string name="app_version">Versión: %1$s&lt;br&gt;Identificador de la construción: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">El Visor del LibreOffice ye un visor de documentos basáu nel LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Esta versión fornióla $VENDOR.</string>
+ <string name="app_name">Visor del LibreOffice</string>
+ <string name="pref_category_general">Xenerales</string>
+ <string name="pref_experimental_editing">Mou esperimental</string>
+ <string name="pref_developer_mode">Mou de desendolcu</string>
+ <string name="action_save_as">Guardar como…</string>
+ <string name="message_saving">Guardando’l documentu…</string>
+ <string name="message_saving_failed">Nun se pudo guardar el documentu.</string>
+ <string name="save_alert_dialog_title">¿Quies guardar el documentu enantes de zarralu\?</string>
+ <string name="save_document">GUARDAR</string>
+ <string name="action_cancel">Encaboxar</string>
+ <string name="about_notice">Amosar l\'avisu</string>
+ <string name="about_privacy_policy">Política de privacidá</string>
+ <string name="create_file">Crear un ficheru nuevu</string>
+ <string name="search_find_next">Atopar siguiente</string>
+ <string name="search_find_previous">Atopar anterior</string>
+ <string name="file_icon_desc">iconu de ficheru</string>
+ <string name="pref_experimental_editing_summary">Activa\'l mou d\'edición esperimental. Úsalu baxo la to responsabilidá.</string>
+ <string name="pref_developer_mode_summary">Activar mou de desendolcu, nel que se puen unviar ordes d\'UNO dientro de l\'app. Úsalu baxo la to responsabilidá.</string>
+ <string name="action_parts">Partes</string>
+ <string name="action_fromat">Activar el formatu</string>
+ <string name="action_UNO_commands">Unviar orde UNO</string>
+ <string name="message_saved">Guardar completu</string>
+ <string name="password">Contraseña</string>
+ <string name="action_presentation">Presentación de diapositives</string>
+ <string name="action_add_slide">Ametar diapositiva</string>
+ <string name="slideshow_action_back">Atrás</string>
+ <string name="calc_insert_before">Inxertar</string>
+ <string name="calc_optimal_length">Llargor óptimu</string>
+ <string name="calc_adjust_length">Axustar el llargor</string>
+ <string name="calc_adjust_width">Axustar l\'anchor</string>
+ <string name="calc_optimal_height">Altor óptimu</string>
+ <string name="calc_optimal_width">Anchor óptimu</string>
+ <string name="calc_optimal_length_confirm">Val</string>
+ <string name="calc_optimal_length_default_text">Pon el llargor extra en centésimes de milímetru</string>
+ <string name="action_add_worksheet">Amestar fueya de cálculu</string>
+ <string name="action_pwd_dialog_OK">Val</string>
+ <string name="action_pwd_dialog_cancel">Encaboxar</string>
+ <string name="action_pwd_dialog_title">Pon la contraseña</string>
+ <string name="take_photo">Facer foto</string>
+ <string name="calc_adjust_height">Axustar l\'altor</string>
+ <string name="calc_alert_double_click_optimal_length">Conseyu: Tocar dos vegaes na testera define l\'anchor/altor óptimu.</string>
+ <string name="select_photo_title">Esbillar una imaxe</string>
+ <string name="no_camera_found">Nun s\'atopó denguna cámara</string>
+ <string name="compress_photo_smallest_size">Tamañu menor</string>
+ <string name="compress_photo_medium_size">Tamañu mediu</string>
+ <string name="compress_photo_max_quality">Calidá máxima</string>
+ <string name="compress_photo_no_compress">Nun comprimir</string>
+ <string name="compress_photo_title">¿Quies comprimir la foto\?</string>
+ <string name="action_copy">Copia</string>
+ <string name="action_paste">Apegar</string>
+ <string name="action_cut">Cortar</string>
+ <string name="action_back">Atrás</string>
+ <string name="action_text_copied">Copióse\'l testu al cartafueyu</string>
+ <string name="insert_table">Inxertar tabla</string>
+ <string name="select_insert_options">Escoyer opciones d\'inxerimientu:</string>
+ <string name="select_delete_options">Escoyer opciones de desaniciu:</string>
+ <string name="action_rename_worksheet">Renomar la fueya de cálculu</string>
+ <string name="action_delete_worksheet">Desaniciar fueya</string>
+ <string name="action_delete_slide">Desaniciar diapositiva</string>
+ <string name="name_already_used">El nome que punxisti yá se ta usando.</string>
+ <string name="part_name_changed">El nome de la parte camudó.</string>
+ <string name="part_deleted">Desanicióse una parte</string>
+ <string name="UNO_commands_string_hint">Orde de UNO</string>
+ <string name="UNO_commands_string_type_hint">Triba</string>
+ <string name="UNO_commands_string_value_hint">Valor</string>
+ <string name="UNO_commands_string_parent_value_hint">Valor cimeru</string>
+ <string name="action_exportToPDF">Esportar a PDF</string>
+ <string name="action_print">Imprentar</string>
+ <string name="tabhost_character">Carácter</string>
+ <string name="tabhost_paragraph">Párrafu</string>
+ <string name="tabhost_insert">Inxertar</string>
+ <string name="tabhost_style">Estilu</string>
+ <string name="alert_ok">Val</string>
+ <string name="alert_cancel">Encaboxar</string>
+ <string name="current_uno_command">Orde d\'UNO actual</string>
+ <string name="display_language">Llingua p\'amosar</string>
+ <string name="select_photo">Esbilla una foto</string>
+ <string name="pdf_export_finished">Acabó la esportación a PDF</string>
+ <string name="unable_to_export_pdf">Nun se pudo esportar a PDF</string>
+ <string name="unable_to_save">Nun se pudo guardar el ficheru</string>
+ <string name="error">Fallu</string>
+ <string name="enter_part_name">Pon un nome pa la parte</string>
+ <string name="bmp_null">El BMP nun val.</string>
+ <string name="slide">Diapositiva</string>
+ <string name="part">Parte</string>
+ <string name="highlight_color">Color de resalte</string>
+ <string name="font_color">Color de la lletra</string>
+ <string name="action_rename_slide">Cambiar el nome de la diapositiva</string>
+ <string name="automatic">Automaticu</string>
+ <string name="display_language_summary">Afitar la llingua predeterminada de la interfaz</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-ca/strings.xml b/android/source/res/values-ca/strings.xml
new file mode 100644
index 000000000000..531bae150b78
--- /dev/null
+++ b/android/source/res/values-ca/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Visualitzador del LibreOffice</string>
+ <string name="app_credits">https://ca.libreoffice.org</string>
+ <string name="action_keyboard">Mostra el teclat</string>
+ <string name="action_save">Desa</string>
+ <string name="action_pwd_dialog_title">Introduïu la contrasenya</string>
+ <string name="take_photo">Fes una foto</string>
+ <string name="action_copy">Copia</string>
+ <string name="action_paste">Enganxa</string>
+ <string name="action_cut">Retalla</string>
+ <string name="action_back">Enrere</string>
+ <string name="tabhost_insert">Insereix</string>
+ <string name="tabhost_style">Estil</string>
+ <string name="page">Pàgina</string>
+ <string name="sheet">Full</string>
+ <string name="slide">Diapositiva</string>
+ <string name="part">Part</string>
+ <string name="automatic">Automàtic</string>
+ <string name="font_color">Color de la lletra</string>
+ <string name="app_name_settings">Paràmetres del visualitzador del LibreOffice</string>
+ <string name="app_description">Aquesta aplicació és un visualitzador de documents basat en el LibreOffice.</string>
+ <string name="readonly_file">Aquest fitxer és només de lectura.</string>
+ <string name="about_license">Mostra la llicència</string>
+ <string name="new_textdocument">Document de text nou</string>
+ <string name="new_presentation">Presentació nova</string>
+ <string name="new_spreadsheet">Full de càlcul nou</string>
+ <string name="new_drawing">Dibuix nou</string>
+ <string name="default_document_name">sense títol</string>
+ <string name="title_recents">Fitxers recents</string>
+ <string name="title_browser">Tots els fitxers</string>
+ <string name="pref_experimental_editing">Mode experimental</string>
+ <string name="pref_developer_mode">Mode de desenvolupament</string>
+ <string name="action_about">Quant a</string>
+ <string name="action_parts">Parts</string>
+ <string name="action_settings">Paràmetres</string>
+ <string name="action_save_as">Anomena i desa…</string>
+ <string name="action_search">Cerca</string>
+ <string name="password">Contrasenya</string>
+ <string name="action_undo">Desfés</string>
+ <string name="action_redo">Refés</string>
+ <string name="save_alert_dialog_title">Voleu desar el document abans de tancar-lo\?</string>
+ <string name="save_document">DESA</string>
+ <string name="no_save_document">NO</string>
+ <string name="action_presentation">Presentació de diapositives</string>
+ <string name="action_add_slide">Afegeix una diapositiva</string>
+ <string name="slideshow_action_back">Enrere</string>
+ <string name="calc_insert_before">Insereix</string>
+ <string name="calc_delete">Suprimeix</string>
+ <string name="calc_hide">Amaga</string>
+ <string name="calc_show">Mostra</string>
+ <string name="insert_table">Insereix una taula</string>
+ <string name="action_delete_slide">Suprimeix la diapositiva</string>
+ <string name="UNO_commands_string_type_hint">Tipus</string>
+ <string name="UNO_commands_string_value_hint">Valor</string>
+ <string name="action_exportToPDF">Exporta com a PDF</string>
+ <string name="action_print">Imprimeix</string>
+ <string name="tabhost_character">Caràcter</string>
+ <string name="tabhost_paragraph">Paràgraf</string>
+ <string name="about_privacy_policy">Política de privadesa</string>
+ <string name="create_file">Crea un fitxer nou</string>
+ <string name="action_cancel">Cancel·la</string>
+ <string name="action_pwd_dialog_cancel">Cancel·la</string>
+ <string name="compress_photo_smallest_size">Mida més petita</string>
+ <string name="select_photo">Tria una foto</string>
+ <string name="select_photo_title">Trieu una imatge</string>
+ <string name="alert_cancel">Cancel·la</string>
+ <string name="enter_part_name">Introduïu un nom per a la part</string>
+ <string name="bmp_null">El BMP no és vàlid.</string>
+ <string name="action_delete_worksheet">Suprimeix el full</string>
+ <string name="highlight_color">Color de realçament</string>
+ <string name="app_version">Versió: %1$s&lt;br&gt;ID de compilació: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_notice">Mostra l\'avís</string>
+ <string name="app_vendor">$VENDOR us proporciona aquesta versió.</string>
+ <string name="select_file_to_open">Trieu el fitxer que voleu obrir</string>
+ <string name="search_find_next">Troba la següent</string>
+ <string name="search_find_previous">Troba l\'anterior</string>
+ <string name="file_icon_desc">icona de fitxer</string>
+ <string name="pref_category_general">General</string>
+ <string name="pref_experimental_editing_summary">Activa el mode d\'edició experimental. Useu-ho sota la vostra responsabilitat.</string>
+ <string name="pref_developer_mode_summary">Activa el mode de desenvolupament per a posar enviar ordres UNO amb l\'aplicació. Useu-ho sota la vostra responsabilitat.</string>
+ <string name="action_fromat">Activa el format</string>
+ <string name="action_UNO_commands">Envia una ordre UNO</string>
+ <string name="message_saving">S\'està desant el document…</string>
+ <string name="message_saving_failed">No s\'ha pogut desar el document.</string>
+ <string name="calc_optimal_length">Longitud òptima</string>
+ <string name="calc_adjust_length">Ajusta la longitud</string>
+ <string name="calc_adjust_height">Ajusta l\'alçada</string>
+ <string name="message_saved">S\'ha desat</string>
+ <string name="calc_adjust_width">Ajusta l\'amplada</string>
+ <string name="calc_optimal_height">Alçada òptima</string>
+ <string name="calc_optimal_width">Amplada òptima</string>
+ <string name="calc_optimal_length_confirm">D\'acord</string>
+ <string name="action_pwd_dialog_OK">D\'acord</string>
+ <string name="calc_optimal_length_default_text">Introduïu la longitud addicional en centèsimes de mil·límetre.</string>
+ <string name="action_add_worksheet">Afegeix un full de càlcul</string>
+ <string name="no_camera_found">No s\'ha trobat cap càmera</string>
+ <string name="compress_photo_medium_size">Mida mitjana</string>
+ <string name="compress_photo_max_quality">Màxima qualitat</string>
+ <string name="compress_photo_no_compress">Sense compressió</string>
+ <string name="compress_photo_title">Voleu comprimir la foto\?</string>
+ <string name="select_insert_options">Trieu les opcions d\'inserció:</string>
+ <string name="select_delete_options">Trieu les opcions de supressió:</string>
+ <string name="action_rename_worksheet">Canvia el nom del full de càcul</string>
+ <string name="name_already_used">El nom facilitat ja és en ús.</string>
+ <string name="UNO_commands_string_hint">Ordre UNO</string>
+ <string name="UNO_commands_string_parent_value_hint">Valor superior</string>
+ <string name="action_text_copied">S\'ha copiat text al porta-retalls</string>
+ <string name="part_name_changed">S\'ha canviat el nom de la part.</string>
+ <string name="part_deleted">S\'ha suprimit la part.</string>
+ <string name="alert_ok">D\'acord</string>
+ <string name="display_language">Llengua de la interfície</string>
+ <string name="display_language_summary">Estableix la llengua predeterminada de la interfície</string>
+ <string name="pdf_export_finished">L\'exportació a PDF ha finalitzat</string>
+ <string name="unable_to_export_pdf">No s\'ha pogut exportar a pdf</string>
+ <string name="current_uno_command">Ordre UNO actual</string>
+ <string name="error">Error</string>
+ <string name="action_rename_slide">Canvia el nom de la diapositiva</string>
+ <string name="unable_to_save">No s\'ha pogut desar el fitxer</string>
+ <string name="calc_alert_double_click_optimal_length">Suggeriment: toqueu dues vegades una capçalera per a establir l\'amplada/alçada òptima.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-cs/strings.xml b/android/source/res/values-cs/strings.xml
new file mode 100644
index 000000000000..ee3bf0bc0b66
--- /dev/null
+++ b/android/source/res/values-cs/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="app_name_settings">Nastavení LibreOffice Viewer</string>
+ <string name="app_description">LibreOffice Viewer je prohlížeč dokumentů založený na LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Toto vydání bylo dodáno společností $VENDOR.</string>
+ <string name="app_version">Verze: %1$s&lt;br&gt;ID sestavení: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_license">Zobrazit licenci</string>
+ <string name="readonly_file">Tento soubor je pouze pro čtení.</string>
+ <string name="about_notice">Zobrazit upozornění</string>
+ <string name="about_privacy_policy">Zásady ochrany osobních údajů</string>
+ <string name="create_file">Vytvořit nový soubor</string>
+ <string name="new_textdocument">Nový textový dokument</string>
+ <string name="new_presentation">Nová prezentace</string>
+ <string name="new_drawing">Nová kresba</string>
+ <string name="default_document_name">bez názvu</string>
+ <string name="new_spreadsheet">Nový sešit</string>
+ <string name="pref_developer_mode_summary">Povolí vývojářský režim, ve kterém lze v aplikaci posílat příkazy UNO. Použití na vlastní nebezpečí.</string>
+ <string name="calc_show">Zobrazit</string>
+ <string name="pref_developer_mode">Vývojářský režim</string>
+ <string name="calc_hide">Skrýt</string>
+ <string name="action_UNO_commands">Poslat příkaz UNO</string>
+ <string name="action_about">O aplikaci</string>
+ <string name="action_fromat">Povolit formát</string>
+ <string name="password">Heslo</string>
+ <string name="select_insert_options">Vyberte možnosti vložení:</string>
+ <string name="slideshow_action_back">Zpět</string>
+ <string name="save_document">ULOŽIT</string>
+ <string name="calc_adjust_length">Upravit délku</string>
+ <string name="select_file_to_open">Vyberte soubor k otevření</string>
+ <string name="save_alert_dialog_title">Uložit dokument před zavřením?</string>
+ <string name="message_saving_failed">Ukládání dokumentu selhalo.</string>
+ <string name="calc_optimal_length">Optimální délka</string>
+ <string name="action_redo">Znovu</string>
+ <string name="title_recents">Poslední soubory</string>
+ <string name="calc_insert_before">Vložit</string>
+ <string name="message_saving">Ukládání dokumentu…</string>
+ <string name="no_save_document">NE</string>
+ <string name="calc_adjust_width">Upravit šířku</string>
+ <string name="action_back">Zpět</string>
+ <string name="pref_experimental_editing">Experimentální režim</string>
+ <string name="calc_delete">Smazat</string>
+ <string name="action_undo">Zpět</string>
+ <string name="action_parts">Části</string>
+ <string name="select_delete_options">Vyberte možnosti smazání:</string>
+ <string name="pref_category_general">Obecné</string>
+ <string name="action_text_copied">Text zkopírován do schránky</string>
+ <string name="action_keyboard">Zobrazit klávesnici</string>
+ <string name="action_presentation">Prezentace</string>
+ <string name="action_search">Hledat</string>
+ <string name="message_saved">Ukládání dokončeno</string>
+ <string name="action_save">Uložit</string>
+ <string name="action_settings">Nastavení</string>
+ <string name="title_browser">Všechny soubory</string>
+ <string name="insert_table">Vložit tabulku</string>
+ <string name="action_add_slide">Přidat snímek</string>
+ <string name="action_cancel">Zrušit</string>
+ <string name="calc_adjust_height">Upravit výšku</string>
+ <string name="pref_experimental_editing_summary">Povolí experimentální režim úprav. Použití na vlastní nebezpečí.</string>
+ <string name="calc_optimal_height">Optimální výška</string>
+ <string name="search_find_next">Najít další</string>
+ <string name="search_find_previous">Najít předchozí</string>
+ <string name="action_save_as">Uložit jako…</string>
+ <string name="file_icon_desc">Ikona souboru</string>
+ <string name="calc_optimal_width">Optimální šířka</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="calc_optimal_length_default_text">Zadejte dodatečnou délku v setinách mm</string>
+ <string name="calc_alert_double_click_optimal_length">Tip: Optimální šířku/výšku nastavíte poklepáním na záhlaví.</string>
+ <string name="action_add_worksheet">Přidat list</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="action_pwd_dialog_cancel">Zrušit</string>
+ <string name="action_pwd_dialog_title">Zadejte heslo</string>
+ <string name="take_photo">Vyfotit</string>
+ <string name="select_photo">Vyberte fotku</string>
+ <string name="select_photo_title">Vyberte obrázek</string>
+ <string name="no_camera_found">Nenalezen fotoaparát</string>
+ <string name="compress_photo_smallest_size">Nejmenší velikost</string>
+ <string name="compress_photo_medium_size">Střední velikost</string>
+ <string name="compress_photo_max_quality">Maximální kvalita</string>
+ <string name="compress_photo_no_compress">Nekomprimovat</string>
+ <string name="compress_photo_title">Přejete si fotku zkomprimovat?</string>
+ <string name="action_paste">Vložit</string>
+ <string name="action_cut">Vyjmout</string>
+ <string name="action_rename_worksheet">Přejmenovat list</string>
+ <string name="action_delete_worksheet">Smazat list</string>
+ <string name="action_delete_slide">Smazat snímek</string>
+ <string name="name_already_used">Zadaný název se již používá.</string>
+ <string name="part_deleted">Část byla smazána.</string>
+ <string name="UNO_commands_string_hint">Příkaz UNO</string>
+ <string name="UNO_commands_string_type_hint">Typ</string>
+ <string name="UNO_commands_string_value_hint">Hodnota</string>
+ <string name="UNO_commands_string_parent_value_hint">Hodnota rodičovského</string>
+ <string name="action_exportToPDF">Exportovat do PDF</string>
+ <string name="action_print">Tisk</string>
+ <string name="tabhost_character">Znak</string>
+ <string name="tabhost_paragraph">Odstavec</string>
+ <string name="tabhost_insert">Vložit</string>
+ <string name="tabhost_style">Styl</string>
+ <string name="alert_ok">OK</string>
+ <string name="alert_cancel">Zrušit</string>
+ <string name="display_language">Jazyk zobrazení</string>
+ <string name="display_language_summary">Nastaví výchozí jazyk zobrazení</string>
+ <string name="pdf_export_finished">Export do PDF dokončen</string>
+ <string name="unable_to_export_pdf">Export do PDF se nepodařil</string>
+ <string name="unable_to_save">Soubor se uložit nepodařilo</string>
+ <string name="error">Chyba</string>
+ <string name="enter_part_name">Zadejte název části</string>
+ <string name="bmp_null">Bmp je prázdný!</string>
+ <string name="page">Stránka</string>
+ <string name="sheet">List</string>
+ <string name="slide">Snímek</string>
+ <string name="part">Část</string>
+ <string name="highlight_color">Barva zvýraznění</string>
+ <string name="font_color">Barva písma</string>
+ <string name="automatic">Automatická</string>
+ <string name="part_name_changed">Název části byl změněn.</string>
+ <string name="current_uno_command">Aktuální příkaz UNO</string>
+ <string name="action_rename_slide">Přejmenovat snímek</string>
+ <string name="action_copy">Kopírovat</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-cy/strings.xml b/android/source/res/values-cy/strings.xml
new file mode 100644
index 000000000000..284265619e18
--- /dev/null
+++ b/android/source/res/values-cy/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="calc_optimal_length">Hyd Gorau</string>
+ <string name="pref_experimental_editing_summary">Galluogi’r modd golygu arbrofol. Gall fod peryglon.</string>
+ <string name="app_name_settings">Gosodiadau LibreOffice Viewer</string>
+ <string name="app_description">Mae LibreOffice Viewer yn ddarllenydd dogfennau yn seiliedig ar LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Darparwyd y fersiwn yma gan $VENDOR.</string>
+ <string name="readonly_file">Darllen yn unig yw\'r ffeil.</string>
+ <string name="about_license">Dangos y Drwydded</string>
+ <string name="about_notice">Dangos yr Hysbysiad</string>
+ <string name="about_privacy_policy">Polisi Preifatrwydd</string>
+ <string name="create_file">Creu Ffeil Newydd</string>
+ <string name="new_textdocument">Dogfen Testun Newydd</string>
+ <string name="new_spreadsheet">Taenlen Newydd</string>
+ <string name="new_drawing">Lluniad Newydd</string>
+ <string name="default_document_name">dideitl</string>
+ <string name="select_file_to_open">Dewis ffeil i\'w hagor</string>
+ <string name="search_find_next">Canfod Nesaf</string>
+ <string name="search_find_previous">Canfod Blaenorol</string>
+ <string name="title_recents">Ffeiliau diweddar</string>
+ <string name="title_browser">Pob ffeil</string>
+ <string name="pref_category_general">Cyffredinol</string>
+ <string name="pref_experimental_editing">Y Modd Arbrofol</string>
+ <string name="pref_developer_mode">Y Modd Datblygwr</string>
+ <string name="action_about">Ynghylch</string>
+ <string name="action_parts">Rhannau</string>
+ <string name="action_settings">Gosodiadau</string>
+ <string name="action_keyboard">Dangos bysellfwrdd</string>
+ <string name="action_save">Cadw</string>
+ <string name="action_save_as">Cadw Fel…</string>
+ <string name="action_fromat">Galluogi Fformat</string>
+ <string name="message_saved">Cwblhawyd y cadw</string>
+ <string name="message_saving">Yn cadw\'r ddogfen…</string>
+ <string name="password">Cyfrinair</string>
+ <string name="action_undo">Dadwneud</string>
+ <string name="action_redo">Ail-wneud</string>
+ <string name="save_document">CADW</string>
+ <string name="action_cancel">Diddymu</string>
+ <string name="no_save_document">NA</string>
+ <string name="action_presentation">Sioe sleidiau</string>
+ <string name="action_add_slide">Ychwanegu Sleid</string>
+ <string name="slideshow_action_back">Nôl</string>
+ <string name="calc_insert_before">Mewnosod</string>
+ <string name="calc_delete">Dileu</string>
+ <string name="calc_hide">Cuddio</string>
+ <string name="calc_show">Dangos</string>
+ <string name="calc_adjust_length">Addasu\'r Hyd</string>
+ <string name="calc_adjust_height">Addasu\'r Uchder</string>
+ <string name="calc_adjust_width">Addasu\'r Lled</string>
+ <string name="calc_optimal_height">Uchder Gorau</string>
+ <string name="calc_optimal_length_confirm">Iawn</string>
+ <string name="calc_alert_double_click_optimal_length">Awgrym: Mae rhoi tap dwbl i bennyn yn gosod y lled/hyd gorau.</string>
+ <string name="action_add_worksheet">Ychwanegu Dalen Waith</string>
+ <string name="action_pwd_dialog_OK">Iawn</string>
+ <string name="action_pwd_dialog_cancel">Diddymu</string>
+ <string name="action_pwd_dialog_title">Rhowch gyfrinair</string>
+ <string name="take_photo">Cymryd Ffoto</string>
+ <string name="select_photo_title">Dewis Llun</string>
+ <string name="no_camera_found">Heb Ganfod Camera</string>
+ <string name="compress_photo_smallest_size">Maint Lleiaf</string>
+ <string name="compress_photo_medium_size">Maint Canolig</string>
+ <string name="compress_photo_max_quality">Ansawdd Gorau</string>
+ <string name="compress_photo_title">Hoffech chi gywasgu\'r ffoto\?</string>
+ <string name="action_cut">Torri</string>
+ <string name="action_back">Nôl</string>
+ <string name="insert_table">Mewnosod tabl</string>
+ <string name="select_insert_options">Dewis dewisiadau mewnosod:</string>
+ <string name="select_delete_options">Dewis dewisiadau dileu:</string>
+ <string name="action_rename_worksheet">Ailenwi dalen waith</string>
+ <string name="action_delete_worksheet">Dileu dalen waith</string>
+ <string name="action_delete_slide">Dileu sleid</string>
+ <string name="action_paste">Gludo</string>
+ <string name="part_deleted">Rhan wedi\'i ddileu.</string>
+ <string name="part_name_changed">Enw rhan wedi newid</string>
+ <string name="UNO_commands_string_parent_value_hint">Gwerth Rhiant</string>
+ <string name="action_exportToPDF">Allforio i PDF</string>
+ <string name="action_print">Argraffu</string>
+ <string name="tabhost_character">Nod</string>
+ <string name="tabhost_paragraph">Paragraff</string>
+ <string name="tabhost_insert">Mewnosod</string>
+ <string name="tabhost_style">Arddull</string>
+ <string name="alert_ok">Iawn</string>
+ <string name="current_uno_command">Y gorchymyn UNO cyfredol</string>
+ <string name="display_language">Iaith Dangos</string>
+ <string name="display_language_summary">Gosod yr iaith dangos ragosodedig</string>
+ <string name="pdf_export_finished">Allforio PDF wedi gorffen</string>
+ <string name="unable_to_export_pdf">Methu allforio i PDF</string>
+ <string name="error">Gwall</string>
+ <string name="enter_part_name">Rho enw rhan</string>
+ <string name="bmp_null">Mae bmp yn nwll!</string>
+ <string name="page">Tudalen</string>
+ <string name="sheet">Dalen</string>
+ <string name="slide">Sleid</string>
+ <string name="part">Rhan</string>
+ <string name="highlight_color">Lliw Amlygu</string>
+ <string name="font_color">Lliw Ffont</string>
+ <string name="action_rename_slide">Ailenwi Sleid</string>
+ <string name="automatic">Awtomatig</string>
+ <string name="new_presentation">Cyflwyniadau Newydd</string>
+ <string name="app_version">Fersiwn: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="pref_developer_mode_summary">Galluogi\'r modd datblygwr lle mae modd i chi anfon gorchmynion UNO o fewn yr ap. Gall fod peryglon.</string>
+ <string name="file_icon_desc">eiconffeil</string>
+ <string name="calc_optimal_length_default_text">Rhoi Hyd Ychwanegol mewn 100fed/mm</string>
+ <string name="select_photo">Dewis Ffoto</string>
+ <string name="name_already_used">Mae\'r enw eisoes yn cael ei ddefnyddio.</string>
+ <string name="action_search">Chwilio</string>
+ <string name="save_alert_dialog_title">Cadw\'r ddogfen cyn cau\?</string>
+ <string name="calc_optimal_width">Lled Gorau</string>
+ <string name="action_UNO_commands">Anfon Cmd UNO</string>
+ <string name="message_saving_failed">Methodd cadw dogfen</string>
+ <string name="compress_photo_no_compress">Peidio Cywasgu</string>
+ <string name="UNO_commands_string_hint">Gorchymyn UNO</string>
+ <string name="UNO_commands_string_value_hint">Gwerth</string>
+ <string name="action_copy">Copïo</string>
+ <string name="action_text_copied">Testun wedi\'i gopïo i\'r clipfwrdd</string>
+ <string name="UNO_commands_string_type_hint">Math</string>
+ <string name="alert_cancel">Diddymu</string>
+ <string name="unable_to_save">Methu cadw i ffeil</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-de/strings.xml b/android/source/res/values-de/strings.xml
index a4f88b2742c4..61f03c9bd63c 100644
--- a/android/source/res/values-de/strings.xml
+++ b/android/source/res/values-de/strings.xml
@@ -1,149 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
-
<string name="app_name">LibreOffice Viewer</string>
<string name="app_name_settings">LibreOffice-Viewer-Einstellungen</string>
-
- <string name="app_about_name"><b>LibreOffice Viewer \'Beta\'</b></string>
- <string name="app_version">Version: %1$s\nBuild ID: %2$s</string>
+ <string name="app_version">Version: %1$s&lt;br&gt;Build ID: &lt;a href="https://hub.libreoffice.org/git-core/%2$s"&gt;%2$s&lt;/a&gt;</string>
<string name="app_description">LibreOffice Viewer ist ein Dokumentenbetrachter, der auf LibreOffice basiert.</string>
<string name="app_credits">https://www.libreoffice.org</string>
<string name="app_vendor">Dieses Release wurde bereitgestellt durch $VENDOR.</string>
- <string name="temp_file_saving_disabled">Diese Datei ist schreibgeschützt, Speichern ist deaktiviert.</string>
-
+ <string name="readonly_file">Diese Datei ist schreibgeschützt.</string>
<string name="about_license">Lizenz anzeigen</string>
<string name="about_notice">Hinweise anzeigen</string>
- <string name="about_moreinfo">Weitere Informationen</string>
- <string name="back_again_to_quit">Zum Beenden noch einmal \'zurück\' drücken</string>
-
+ <string name="about_privacy_policy">Datenschutzerklärung</string>
<string name="new_textdocument">Neues Textdokument</string>
<string name="new_presentation">Neue Präsentation</string>
<string name="new_spreadsheet">Neues Tabellendokument</string>
<string name="new_drawing">Neue Zeichnung</string>
<string name="default_document_name">unbenannt</string>
-
- <string name="browser_app_name">LibreOffice Browser</string>
- <string name="menu_search">Suchen</string>
- <string name="list_view">Liste</string>
- <string name="grid_view">Gitter</string>
- <string name="filter">Filtern nach</string>
- <string name="search_not_found">Suchbegriff nicht gefunden</string>
- <string name="sort">Sortieren nach</string>
- <string name="sort_smallest">Kleinste zuerst</string>
- <string name="sort_largest">Größte zuerst</string>
- <string name="sort_az">A-Z</string>
- <string name="sort_za">Z-A</string>
- <string name="sort_oldest">Älteste zuerst</string>
- <string name="sort_newest">Neueste zuerst</string>
- <string name="menu_sort_size">Nach Größe sortieren</string>
- <string name="menu_sort_az">Von A bis Z sortieren</string>
- <string name="menu_sort_modified">Nach Datum sortieren</string>
- <string name="menu_preferences">Einstellungen</string>
+ <string name="select_file_to_open">Datei zum Öffnen auswählen</string>
<string name="file_icon_desc">Datei-Icon</string>
<string name="title_recents">Zuletzt verwendete Dateien</string>
<string name="title_browser">Alle Dateien</string>
- <!-- Pref keys as resources ; Not currently used -->
- <string name="EXPLORER_VIEW_TYPE_KEY">EXPLORER_VIEW_TYPE</string>
- <string name="CURRENT_DIRECTORY_KEY">CURRENT_DIRECTORY</string>
- <string name="pref_category_explorer">Dateimanager-Einstellungen</string>
<string name="pref_category_general">Allgemein</string>
<string name="pref_experimental_editing">Experimenteller Modus</string>
<string name="pref_experimental_editing_summary">Den experimentellen Editier-Modus aktivieren. Verwendung auf eigene Gefahr.</string>
- <string name="pref_show_hidden_files">Versteckte Dateien/Ordner</string>
- <string name="pref_show_hidden_files_summary">Anzeige versteckter Dateien/Ordner aktivieren</string>
<string name="pref_developer_mode">Entwickler-Modus</string>
<string name="pref_developer_mode_summary">Entwickler-Modus, in dem in der App UNO-Kommandos gesendet werden können. Verwendung auf eigene Gefahr.</string>
-
<string name="action_about">Info</string>
<string name="action_parts">Abschnitte</string>
<string name="action_settings">Einstellungen</string>
- <string name="open">Öffnen</string>
- <string name="share">Teilen</string>
- <string name="share_via">Teilen via</string>
-
- <!-- Document browser filters -->
- <string name="filter_everything">Alles</string>
- <string name="filter_documents">Dokumente</string>
- <string name="filter_spreadsheets">Tabellendokumente</string>
- <string name="filter_presentations">Präsentationen</string>
- <string name="filter_drawings">Zeichnungen</string>
-
- <!-- Document provider names -->
- <string name="document_locations">Dokumentenorte</string>
- <string name="close_document_locations">Dokumentenorte schließen</string>
- <string name="local_documents">Dokumentenverzeichnis</string>
- <string name="local_file_system">Lokales Dateisystem</string>
- <string name="external_sd_file_system">Externe SD</string>
- <string name="otg_file_system">OTG-Gerät (experimentell)</string>
- <string name="owncloud">Entfernter Server</string>
- <string name="usb_connected_configure">USB verbunden, richten Sie Ihr Gerät ein.</string>
-
- <string name="owncloud_wrong_connection">Verbindung mit dem ownCloud-Server nicht möglich. Prüfen Sie die Einstellungen.</string>
- <string name="owncloud_unauthorized">Anmeldung am ownCloud-Server nicht möglich. Prüfen Sie die Einstellungen.</string>
- <string name="owncloud_unspecified_error">Nicht näher spezifizierter Fehler beim Verbindungsaufbau zum ownCloud-Server. Prüfen Sie die Einstellungen und/oder versuchen Sie es später.</string>
-
- <string name="ext_document_provider_error">Ungültige Wurzel-Datei. Prüfen Sie die SD-Karten-Einstellungen.</string>
- <string name="legacy_extsd_missing_error">Ungültige Wurzel-Datei. Prüfen Sie die externe SD-Karte und/oder die Einstellungen</string>
- <string name="otg_missing_error">Ungültige Wurzel-Datei. Prüfen Sie Ihr OTG-Gerät und/oder die Einstellungen.</string>
-
<!-- Edit action names -->
- <string name="action_bold">Fett</string>
- <string name="action_underline">Unterstrichen</string>
- <string name="action_italic">Kursiv</string>
- <string name="action_strikeout">Durchgestrichen</string>
<string name="action_keyboard">Tastatur anzeigen</string>
<string name="action_save">Speichern</string>
+ <string name="action_save_as">Speichern unter…</string>
<string name="action_fromat">Format anwenden</string>
<string name="action_search">Suchen</string>
<string name="action_UNO_commands">UNO-Kommando senden</string>
-
<!-- Feedback messages -->
<string name="message_saved">Speichern beendet</string>
<string name="message_saving">Dokument wird gespeichert…</string>
- <string name="message_save_incomplete">Speichern unvollständig. Gab es Änderungen?</string>
- <string name="create_new_file_success">"Neue Datei angelegt - "</string>
- <string name="create_new_file_error">Neue Datei konnte nicht angelegt weden, bitte Prüfen Sie den eingegeben Dateinamen.</string>
-
- <!-- Document provider settings -->
- <string name="storage_provider_settings">Speicheranbieter-Einstellungen</string>
- <string name="owncloud_settings">ownCloud-Einstellungen</string>
- <string name="physical_storage_settings">Einstellungen für physikalischen Speicher</string>
- <string name="external_sd_path">Pfad zur externen SD-Karte</string>
- <string name="otg_device_path">Pfad zum OTG-Gerät</string>
- <string name="otg_warning">Experimentelles Feature: Nur verwenden, wenn OTG-Gerät beschreibbar ist.</string>
- <string name="server_url">Server-URL</string>
- <string name="server_url_and_port">URL und Port des ownCloud-Servers.</string>
- <string name="user_name">Benutzername</string>
+ <string name="message_saving_failed">Speichern des Dokuments ist fehlgeschlagen.</string>
<string name="password">Passwort</string>
<string name="action_undo">Rückgängig</string>
<string name="action_redo">Wiederherstellen</string>
-
- <!-- Directory browser strings -->
- <string name="up_description">Nach oben</string>
- <string name="confirm_label">Bestätigen</string>
- <string name="cancel_label">Abbrechen</string>
- <string name="search_label">Los</string>
- <string name="directory_browser_label">Verzeichnis auswählen</string>
- <string name="bad_directory">Ungültiger Verzeichnispfad</string>
- <string name="current_dir">Aktuelles Verzeichnis: %1$s</string>
-
<!-- Save Alert dialog strings -->
<string name="save_alert_dialog_title">Dokument vor dem Schließen speichern?</string>
<string name="save_document">SPEICHERN</string>
<string name="action_cancel">Abbrechen</string>
<string name="no_save_document">NEIN</string>
-
- <!-- Create New Document Dialog Strings -->
- <string name="create_new_document_title">Dateiname eingeben</string>
- <string name="action_create">ANLEGEN</string>
-
<!-- Presentation Mode Strings -->
<string name="action_presentation">Präsentation</string>
<string name="action_add_slide">Folie hinzufügen</string>
- <string name="alert_copy_svg_slide_show_to_clipboard">Ihr Android-Gerät unterstützt keine In-App-SVG-Präsentation. Wir haben den Link zur Präsentation in die Zwischenablage kopiert. Drücken Sie den Home-Button, öffnen Sie einen modernen Web-Browser, fügen Sie in die Adressleiste ein und los.</string>
- <string name="alert_copy_svg_slide_show_to_clipboard_dismiss">OK</string>
<string name="slideshow_action_back">Zurück</string>
-
<!-- Calc Header Menu Strings -->
<string name="calc_insert_before">Einfügen</string>
<string name="calc_delete">Löschen</string>
@@ -159,12 +65,10 @@
<string name="calc_optimal_length_default_text">Geben Sie die zusätzliche Höhe in 100tel/mm ein</string>
<string name="calc_alert_double_click_optimal_length">Hinweis: Doppeltes Antippen auf eine Überschrift setzt die optimale Breite/Höhe.</string>
<string name="action_add_worksheet">Arbeitsblatt hinzufügen</string>
-
<!-- Password dialog strings -->
<string name="action_pwd_dialog_OK">OK</string>
<string name="action_pwd_dialog_cancel">Abbrechen</string>
<string name="action_pwd_dialog_title">Bitte Passwort eingeben</string>
-
<!-- Insert Image Strings -->
<string name="take_photo">Foto Machen</string>
<string name="select_photo">Foto Auswählen</string>
@@ -175,7 +79,6 @@
<string name="compress_photo_max_quality">Maximale Qualität</string>
<string name="compress_photo_no_compress">Nicht komprimieren</string>
<string name="compress_photo_title">Wollen Sie das Foto komprimieren?</string>
-
<!-- Clipboard Actions -->
<string name="action_copy">Kopieren</string>
<string name="action_paste">Einfügen</string>
@@ -203,7 +106,6 @@
<item>Spalten Löschen</item>
<item>Tabelle Löschen</item>
</string-array>
-
<!-- UNO cmd controller Strings -->
<string name="UNO_commands_string_hint">UNO-Kommando</string>
<string name="UNO_commands_string_type_hint">Typ</string>
@@ -217,23 +119,15 @@
<string name="tabhost_style">Format</string>
<string name="alert_ok">OK</string>
<string name="alert_cancel">Abbrechen</string>
- <string name="unable_to_go_further">Kann nicht weiter gehen.</string>
<string name="current_uno_command">Aktuelles UNO-Kommando</string>
- <string name="pref_sort_summary">Sortiermodus für Dateien auswählen: A-Z, nach Größe oder nach Datum.</string>
- <string name="pref_viewmode_summary">Dateien als Gitter oder als Liste anzeigen.</string>
- <string name="pref_file_explorer_title">Dateimanager-Layout</string>
- <string name="pref_sort_title">Datei-Reihenfolge</string>
- <string name="pref_filter_title">Standard-Dateifilter</string>
- <string name="pref_filter_summary">Wählen Sie, welcher Dateifilter standardmäßig verwendet werden soll.</string>
<string name="display_language">Anzeigesprache</string>
<string name="display_language_summary">Wählen Sie die Standard-Anzeigesprache</string>
+ <string name="pdf_export_finished">PDF-Export abgeschlossen</string>
<string name="unable_to_export_pdf">PDF-Export nicht möglich</string>
- <string name="pdf_exported_at">PDF exportiert nach</string>
- <string name="printing_not_supported">Ihr Gerät unterstützt Drucken nicht</string>
+ <string name="unable_to_save">Speichern nicht möglich</string>
<string name="error">Fehler</string>
<string name="enter_part_name">Name für Abschnitt eingeben</string>
<string name="bmp_null">Bmp ist null!</string>
- <string name="directory_not_saved">Verzeichnis nicht gespeichert.</string>
<string name="page">Seite</string>
<string name="sheet">Arbeitsblatt</string>
<string name="slide">Folie</string>
@@ -241,4 +135,8 @@
<string name="highlight_color">Hervorhebungs-Farbe</string>
<string name="font_color">Schriftfarbe</string>
<string name="action_rename_slide">Folie umbenennen</string>
-</resources>
+ <string name="automatic">Automatisch</string>
+ <string name="create_file">Neue Datei erstellen</string>
+ <string name="search_find_next">Nächste suchen</string>
+ <string name="search_find_previous">Vorherige suchen</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-dsb/strings.xml b/android/source/res/values-dsb/strings.xml
new file mode 100644
index 000000000000..b1885d60a18e
--- /dev/null
+++ b/android/source/res/values-dsb/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="calc_hide">Schowaś</string>
+ <string name="compress_photo_title">Cośo foto kompriměrowaś\?</string>
+ <string name="app_name_settings">Nastajenja LibreOffice Viewer</string>
+ <string name="app_description">LibreOffice Viewer jo dokumentowy wobglědowak, kótaryž na LibreOffice bazěrujo.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Toś to wózjawjenje jo se stajiło wót $VENDOR k dispoziciji.</string>
+ <string name="readonly_file">Toś ta dataja jo pśeśiwo pisanjeju šćitana.</string>
+ <string name="about_notice">Powěźeńku pokazaś</string>
+ <string name="create_file">Nowu dataju napóraś</string>
+ <string name="new_textdocument">Nowy tekstowy dokument</string>
+ <string name="new_presentation">Nowa prezentacija</string>
+ <string name="new_spreadsheet">Nowy tabelowy dokument</string>
+ <string name="new_drawing">Nowa kreslanka</string>
+ <string name="default_document_name">bźez titela</string>
+ <string name="select_file_to_open">Wubjeŕśo dataju, kótaraž se ma wócyniś</string>
+ <string name="about_license">Licencu pokazaś</string>
+ <string name="about_privacy_policy">Pšawidła priwatnosći</string>
+ <string name="calc_adjust_length">Dłujkosć pśiměriś</string>
+ <string name="search_find_previous">Pjerwjejšny pytaś</string>
+ <string name="file_icon_desc">datajowy symbol</string>
+ <string name="title_recents">Nejnowše dataje</string>
+ <string name="pref_category_general">Powšykne</string>
+ <string name="pref_experimental_editing">Eksperimentelny modus</string>
+ <string name="pref_experimental_editing_summary">Eksperimentelny wobźěłański modus zmóžniś. Wužywanje na swójske riziko.</string>
+ <string name="pref_developer_mode">Wuwijaŕski modus</string>
+ <string name="action_about">Wó</string>
+ <string name="action_parts">Źěle</string>
+ <string name="action_settings">Nastajenja</string>
+ <string name="action_keyboard">Tastaturu pokazaś</string>
+ <string name="action_save">Składowaś</string>
+ <string name="action_save_as">Składowaś ako…</string>
+ <string name="action_fromat">Format zmóžniś</string>
+ <string name="action_search">Pytaś</string>
+ <string name="action_UNO_commands">Pśikaz UNO pósłaś</string>
+ <string name="message_saved">Składowanje dokóńcone</string>
+ <string name="message_saving">Dokument se składujo…</string>
+ <string name="message_saving_failed">Składowanje dokumenta njejo se raźiło.</string>
+ <string name="password">Gronidło</string>
+ <string name="action_undo">Anulěrowaś</string>
+ <string name="action_redo">Wóspjetowaś</string>
+ <string name="save_document">SKŁADOWAŚ</string>
+ <string name="action_cancel">Pśetergnuś</string>
+ <string name="no_save_document">NĚ</string>
+ <string name="action_presentation">Prezentacija</string>
+ <string name="action_add_slide">Foliju pśidaś</string>
+ <string name="slideshow_action_back">Slědk</string>
+ <string name="calc_insert_before">Zasajźiś</string>
+ <string name="calc_delete">Wulašowaś</string>
+ <string name="calc_show">Pokazaś</string>
+ <string name="calc_optimal_length">Optimalna dłujkosć</string>
+ <string name="calc_adjust_height">Wusokosć pśiměriś</string>
+ <string name="calc_adjust_width">Šyrokosć pśiměriś</string>
+ <string name="calc_optimal_height">Optimalna wusokosć</string>
+ <string name="calc_optimal_width">Optimalna šyrokosć</string>
+ <string name="calc_optimal_length_confirm">W pórěźe</string>
+ <string name="calc_optimal_length_default_text">Zapódajśo pśidatnu dłujkosć w 100tych mm</string>
+ <string name="action_add_worksheet">Źěłowe łopjeno pśidaś</string>
+ <string name="action_pwd_dialog_OK">W pórěźe</string>
+ <string name="action_pwd_dialog_cancel">Pśetergnuś</string>
+ <string name="action_pwd_dialog_title">Zapódajśo pšosym gronidło</string>
+ <string name="take_photo">Foto gótowaś</string>
+ <string name="select_photo">Foto wubraś</string>
+ <string name="select_photo_title">Wobraz wubraś</string>
+ <string name="no_camera_found">Žedna kamera namakana</string>
+ <string name="compress_photo_smallest_size">Nejmjeńša wjelikosć</string>
+ <string name="compress_photo_medium_size">Srjejźna wjelikosć</string>
+ <string name="compress_photo_max_quality">Maksimalna kwalita</string>
+ <string name="compress_photo_no_compress">Njekompriměrowaś</string>
+ <string name="action_copy">Kopěrowaś</string>
+ <string name="action_paste">Zasajźiś</string>
+ <string name="action_cut">Wurězaś</string>
+ <string name="action_back">Slědk</string>
+ <string name="action_text_copied">Tekst jo se kopěrował do mjazywótkłada</string>
+ <string name="insert_table">Tabelu zasajźiś</string>
+ <string name="select_insert_options">Zasajźeńske nastajenja wubraś:</string>
+ <string name="select_delete_options">Lašowańske nastajenja wubraś:</string>
+ <string name="action_rename_worksheet">Źěłowe łopjeno pśemjeniś</string>
+ <string name="action_delete_worksheet">Źěłowe łopjeno wulašowaś</string>
+ <string name="action_delete_slide">Foliju wulašowaś</string>
+ <string name="name_already_used">Pódane mě se južo wužywa.</string>
+ <string name="part_name_changed">Mě źěla jo se změniło.</string>
+ <string name="part_deleted">Źěl jo se wulašował.</string>
+ <string name="UNO_commands_string_hint">Pśikaz UNO</string>
+ <string name="UNO_commands_string_type_hint">Typ</string>
+ <string name="UNO_commands_string_value_hint">Gódnota</string>
+ <string name="UNO_commands_string_parent_value_hint">Nadrědowana gódnota</string>
+ <string name="action_exportToPDF">Ako PDF eksportěrowaś</string>
+ <string name="action_print">Śišćaś</string>
+ <string name="tabhost_character">Znamuško</string>
+ <string name="tabhost_paragraph">Wótstawk</string>
+ <string name="tabhost_insert">Zasajźiś</string>
+ <string name="tabhost_style">Pśedłoga</string>
+ <string name="alert_ok">W pórěźe</string>
+ <string name="alert_cancel">Pśetergnuś</string>
+ <string name="current_uno_command">Aktualny pśikaz UNO</string>
+ <string name="display_language">Pokazowańska rěc</string>
+ <string name="display_language_summary">Nastajśo standardnu pokazowańsku rěc</string>
+ <string name="pdf_export_finished">Eksport ako PDF dokóńcony</string>
+ <string name="unable_to_export_pdf">Eksport ako PDF njejo móžny</string>
+ <string name="unable_to_save">Dataja njedajo se składowaś</string>
+ <string name="error">Zmólka</string>
+ <string name="enter_part_name">Mě źěla zapódaś</string>
+ <string name="bmp_null">Bmp jo nul!</string>
+ <string name="page">Bok</string>
+ <string name="sheet">Tabela</string>
+ <string name="slide">Folija</string>
+ <string name="part">Źěl</string>
+ <string name="highlight_color">Barwa za wuzwignjenja</string>
+ <string name="font_color">Pismowa barwa</string>
+ <string name="action_rename_slide">Foliju pśemjeniś</string>
+ <string name="automatic">Awtomatiski</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="app_version">Wersija: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="search_find_next">Dalej pytaś</string>
+ <string name="title_browser">Wšykne dataje</string>
+ <string name="pref_developer_mode_summary">Wuwijaŕski modus zmóžniś, źož móžośo pśikaze UNO w nałoženju pósłaś. Wužywanje na swójske riziko.</string>
+ <string name="save_alert_dialog_title">Dokument do zacynjanja składowaś\?</string>
+ <string name="calc_alert_double_click_optimal_length">Pokaz: Pótusniśo dwójcy nadpismo, aby optimalnu šyrokosć/wusokosć nastajił.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-el/strings.xml b/android/source/res/values-el/strings.xml
new file mode 100644
index 000000000000..4de4e2c60047
--- /dev/null
+++ b/android/source/res/values-el/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="create_file">Δημιουργία νέου αρχείου</string>
+ <string name="message_saving_failed">Αποτυχία αποθήκευσης του εγγράφου.</string>
+ <string name="action_presentation">Προβολή παρουσίασης</string>
+ <string name="app_name">Προβολή LibreOffice</string>
+ <string name="app_name_settings">Ρυθμίσεις της προβολής του LibreOffice</string>
+ <string name="app_description">Η προβολή του LibreOffice είναι ένα πρόγραμμα προβολής εγγράφων που βασίζεται στο LibreOffice.</string>
+ <string name="select_file_to_open">Επιλέξτε αρχείο για άνοιγμα</string>
+ <string name="pref_experimental_editing">Πειραματική λειτουργία</string>
+ <string name="action_keyboard">Εμφάνιση πληκτρολογίου</string>
+ <string name="app_version">Έκδοση: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Αυτή η έκδοση παρέχεται από την $VENDOR.</string>
+ <string name="readonly_file">Αυτό το αρχείο είναι μόνο για ανάγνωση.</string>
+ <string name="about_license">Εμφάνιση άδειας</string>
+ <string name="about_notice">Εμφάνιση σημείωσης</string>
+ <string name="about_privacy_policy">Πολιτική απορρήτου</string>
+ <string name="new_textdocument">Νέο έγγραφο κειμένου</string>
+ <string name="new_presentation">Νέα παρουσίαση</string>
+ <string name="new_spreadsheet">Νέο υπολογιστικό φύλλο</string>
+ <string name="new_drawing">Νέο σχέδιο</string>
+ <string name="default_document_name">χωρίς τίτλο</string>
+ <string name="search_find_next">Εύρεση επόμενου</string>
+ <string name="search_find_previous">Εύρεση προηγούμενου</string>
+ <string name="file_icon_desc">Εικονίδιο αρχείου</string>
+ <string name="title_recents">Πρόσφατα αρχεία</string>
+ <string name="title_browser">Όλα τα αρχεία</string>
+ <string name="pref_category_general">Γενικά</string>
+ <string name="pref_developer_mode">Λειτουργία ανάπτυξης</string>
+ <string name="pref_developer_mode_summary">Ενεργοποίηση της λειτουργίας προγραμματιστή όπου μπορείτε να στείλετε εντολές UNO εντός της εφαρμογής. Χρησιμοποιήστε το με δική σας ευθύνη.</string>
+ <string name="action_about">Περί</string>
+ <string name="action_parts">Τμήματα</string>
+ <string name="action_settings">Ρυθμίσεις</string>
+ <string name="action_save">Αποθήκευση</string>
+ <string name="action_save_as">Αποθήκευση ως…</string>
+ <string name="action_fromat">Ενεργοποίηση μορφής</string>
+ <string name="message_saved">Ολοκλήρωση αποθήκευσης</string>
+ <string name="message_saving">Αποθήκευση του εγγράφου…</string>
+ <string name="password">Κωδικός πρόσβασης</string>
+ <string name="action_undo">Αναίρεση</string>
+ <string name="action_redo">Ακύρωση αναίρεσης</string>
+ <string name="save_alert_dialog_title">Να αποθηκευτεί το έγγραφο πριν το κλείσιμο;</string>
+ <string name="save_document">ΑΠΟΘΗΚΕΥΣΗ</string>
+ <string name="action_cancel">Ακύρωση</string>
+ <string name="no_save_document">ΟΧΙ</string>
+ <string name="action_add_slide">Προσθήκη διαφάνειας</string>
+ <string name="slideshow_action_back">Πίσω</string>
+ <string name="calc_insert_before">Εισαγωγή</string>
+ <string name="calc_delete">Διαγραφή</string>
+ <string name="calc_hide">Απόκρυψη</string>
+ <string name="calc_show">Εμφάνιση</string>
+ <string name="calc_optimal_length">Βέλτιστο μήκος</string>
+ <string name="calc_adjust_length">Προσαρμογή μήκους</string>
+ <string name="calc_adjust_height">Προσαρμογή ύψους</string>
+ <string name="calc_optimal_height">Βέλτιστο ύψος</string>
+ <string name="calc_optimal_width">Βέλτιστο πλάτος</string>
+ <string name="calc_optimal_length_confirm">Εντάξει</string>
+ <string name="calc_alert_double_click_optimal_length">Συμβουλή: Το διπλό πάτημα σε μια κεφαλίδα ορίζει το βέλτιστο πλάτος/ύψος.</string>
+ <string name="action_add_worksheet">Προσθήκη φύλλου εργασίας</string>
+ <string name="action_pwd_dialog_OK">Εντάξει</string>
+ <string name="action_pwd_dialog_cancel">Ακύρωση</string>
+ <string name="action_pwd_dialog_title">Παρακαλούμε εισάγετε τον κωδικό πρόσβασης</string>
+ <string name="take_photo">Λήψη φωτογραφίας</string>
+ <string name="pref_experimental_editing_summary">Ενεργοποίηση της πειραματικής λειτουργίας επεξεργασίας. Χρησιμοποιήστε την με δική σας ευθύνη.</string>
+ <string name="action_search">Αναζήτηση</string>
+ <string name="action_UNO_commands">Αποστολή εντολής UNO</string>
+ <string name="calc_adjust_width">Προσαρμογή πλάτους</string>
+ <string name="calc_optimal_length_default_text">Εισαγάγετε επιπλέον μήκος σε 100στά/mm</string>
+ <string name="select_photo">Επιλογή φωτογραφίας</string>
+ <string name="select_photo_title">Επιλογή εικόνας</string>
+ <string name="no_camera_found">Δεν βρέθηκε κάμερα</string>
+ <string name="compress_photo_smallest_size">Ελάχιστο μέγεθος</string>
+ <string name="compress_photo_medium_size">Μεσαίο μέγεθος</string>
+ <string name="compress_photo_max_quality">Μέγιστη ποιότητα</string>
+ <string name="compress_photo_no_compress">Να μην συμπιεστεί</string>
+ <string name="compress_photo_title">Θέλετε να συμπιέσετε τη φωτογραφία;</string>
+ <string name="action_copy">Αντιγραφή</string>
+ <string name="action_paste">Επικόλληση</string>
+ <string name="action_cut">Αποκοπή</string>
+ <string name="action_back">Πίσω</string>
+ <string name="action_text_copied">Το κείμενο αντιγράφηκε στο πρόχειρο</string>
+ <string name="insert_table">Εισαγωγή πίνακα</string>
+ <string name="select_delete_options">Διαλέξτε επιλογές διαγραφής:</string>
+ <string name="action_rename_worksheet">Μετονομασία φύλλου εργασίας</string>
+ <string name="action_delete_worksheet">Διαγραφή φύλλου εργασίας</string>
+ <string name="action_delete_slide">Διαγραφή διαφάνειας</string>
+ <string name="part_deleted">Το τμήμα έχει διαγραφεί.</string>
+ <string name="UNO_commands_string_hint">Εντολή UNO</string>
+ <string name="UNO_commands_string_type_hint">Τύπος</string>
+ <string name="UNO_commands_string_value_hint">Τιμή</string>
+ <string name="UNO_commands_string_parent_value_hint">Γονική τιμή</string>
+ <string name="action_exportToPDF">Εξαγωγή σε PDF</string>
+ <string name="action_print">Εκτύπωση</string>
+ <string name="tabhost_character">Χαρακτήρας</string>
+ <string name="tabhost_insert">Εισαγωγή</string>
+ <string name="part_name_changed">Το όνομα του τμήματος άλλαξε.</string>
+ <string name="tabhost_style">Τεχνοτροπία</string>
+ <string name="alert_ok">Εντάξει</string>
+ <string name="alert_cancel">Ακύρωση</string>
+ <string name="current_uno_command">Τρέχουσα εντολή UNO</string>
+ <string name="display_language">Εμφάνιση γλώσσας</string>
+ <string name="display_language_summary">Ορίστε την προεπιλεγμένη γλώσσα εμφάνισης</string>
+ <string name="pdf_export_finished">Η εξαγωγή PDF ολοκληρώθηκε</string>
+ <string name="unable_to_export_pdf">Αδυναμία εξαγωγής σε pdf</string>
+ <string name="unable_to_save">Αδυναμία αποθήκευσης του αρχείου</string>
+ <string name="error">Σφάλμα</string>
+ <string name="bmp_null">Το Bmp είναι null!</string>
+ <string name="page">Σελίδα</string>
+ <string name="sheet">Φύλλο</string>
+ <string name="slide">Διαφάνεια</string>
+ <string name="part">Τμήμα</string>
+ <string name="highlight_color">Χρώμα επισήμανσης</string>
+ <string name="font_color">Χρώμα γραμματοσειράς</string>
+ <string name="action_rename_slide">Μετονομασία διαφάνειας</string>
+ <string name="automatic">Αυτόματα</string>
+ <string name="enter_part_name">Εισαγάγετε ένα όνομα του τμήματος</string>
+ <string name="select_insert_options">Διαλέξτε επιλογές εισαγωγής:</string>
+ <string name="name_already_used">Το συγκεκριμένο όνομα χρησιμοποιείται ήδη.</string>
+ <string name="tabhost_paragraph">Παράγραφος</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-es/strings.xml b/android/source/res/values-es/strings.xml
new file mode 100644
index 000000000000..0dbbf6fbf522
--- /dev/null
+++ b/android/source/res/values-es/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="no_camera_found">No se encontró ninguna cámara</string>
+ <string name="app_name">Visor de LibreOffice</string>
+ <string name="action_presentation">Pase de diapositivas</string>
+ <string name="calc_delete">Eliminar</string>
+ <string name="app_vendor">$VENDOR le proporciona esta versión.</string>
+ <string name="pref_experimental_editing">Modo experimental</string>
+ <string name="app_name_settings">Configuración del visor de LibreOffice</string>
+ <string name="app_version">Versión: %1$s&lt;br&gt;Id. de montaje: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">Esta aplicación es un visor de documentos basado en LibreOffice.</string>
+ <string name="app_credits">https://es.libreoffice.org</string>
+ <string name="readonly_file">Este archivo es de solo lectura.</string>
+ <string name="about_license">Mostrar licencia</string>
+ <string name="about_notice">Mostrar aviso</string>
+ <string name="about_privacy_policy">Normativa de privacidad</string>
+ <string name="create_file">Crear un archivo</string>
+ <string name="new_textdocument">Documento de texto nuevo</string>
+ <string name="new_presentation">Presentación nueva</string>
+ <string name="new_spreadsheet">Libro nuevo</string>
+ <string name="new_drawing">Dibujo nuevo</string>
+ <string name="default_document_name">sin título</string>
+ <string name="select_file_to_open">Seleccione un archivo para abrirlo</string>
+ <string name="search_find_next">Buscar siguiente</string>
+ <string name="search_find_previous">Buscar anterior</string>
+ <string name="file_icon_desc">icono de archivo</string>
+ <string name="title_recents">Archivos recientes</string>
+ <string name="title_browser">Todos los archivos</string>
+ <string name="pref_category_general">Generales</string>
+ <string name="pref_experimental_editing_summary">Activar el modo de edición experimental. Úselo bajo su responsabilidad.</string>
+ <string name="pref_developer_mode">Modo de desarrollo</string>
+ <string name="action_about">Acerca de</string>
+ <string name="action_parts">Partes</string>
+ <string name="action_settings">Configuración</string>
+ <string name="action_keyboard">Mostrar teclado</string>
+ <string name="action_save">Guardar</string>
+ <string name="action_save_as">Guardar como…</string>
+ <string name="action_fromat">Activar formato</string>
+ <string name="action_search">Buscar</string>
+ <string name="message_saved">Se completó el guardado</string>
+ <string name="message_saving">Guardando el documento…</string>
+ <string name="message_saving_failed">No se pudo guardar el documento.</string>
+ <string name="password">Contraseña</string>
+ <string name="action_undo">Deshacer</string>
+ <string name="action_redo">Rehacer</string>
+ <string name="save_alert_dialog_title">¿Quiere guardar el documento antes de cerrarlo\?</string>
+ <string name="save_document">GUARDAR</string>
+ <string name="action_cancel">Cancelar</string>
+ <string name="no_save_document">NO</string>
+ <string name="action_add_slide">Añadir diapositiva</string>
+ <string name="slideshow_action_back">Atrás</string>
+ <string name="calc_insert_before">Insertar</string>
+ <string name="calc_hide">Ocultar</string>
+ <string name="calc_show">Mostrar</string>
+ <string name="calc_optimal_length">Longitud óptima</string>
+ <string name="calc_adjust_length">Ajustar longitud</string>
+ <string name="calc_adjust_height">Ajustar altura</string>
+ <string name="calc_adjust_width">Ajustar anchura</string>
+ <string name="calc_optimal_width">Anchura óptima</string>
+ <string name="calc_optimal_length_confirm">Aceptar</string>
+ <string name="action_add_worksheet">Añadir hoja de cálculo</string>
+ <string name="action_pwd_dialog_OK">Aceptar</string>
+ <string name="action_pwd_dialog_cancel">Cancelar</string>
+ <string name="action_pwd_dialog_title">Introduzca la contraseña</string>
+ <string name="take_photo">Hacer foto</string>
+ <string name="select_photo">Seleccionar foto</string>
+ <string name="select_photo_title">Seleccionar imagen</string>
+ <string name="compress_photo_smallest_size">Tamaño menor</string>
+ <string name="compress_photo_medium_size">Tamaño medio</string>
+ <string name="compress_photo_max_quality">Calidad máxima</string>
+ <string name="compress_photo_no_compress">No comprimir</string>
+ <string name="compress_photo_title">¿Quiere comprimir la foto\?</string>
+ <string name="action_copy">Copiar</string>
+ <string name="action_paste">Pegar</string>
+ <string name="action_cut">Cortar</string>
+ <string name="action_back">Atrás</string>
+ <string name="action_text_copied">Se copió el texto en el portapapeles</string>
+ <string name="insert_table">Insertar tabla</string>
+ <string name="select_insert_options">Seleccionar opciones de inserción:</string>
+ <string name="select_delete_options">Seleccionar opciones de eliminación:</string>
+ <string name="action_rename_worksheet">Cambiar nombre de hoja</string>
+ <string name="action_delete_worksheet">Eliminar hoja</string>
+ <string name="action_delete_slide">Eliminar diapositiva</string>
+ <string name="name_already_used">El nombre proporcionado ya se utiliza.</string>
+ <string name="part_name_changed">Se cambió el nombre de la parte.</string>
+ <string name="part_deleted">Se eliminó la parte.</string>
+ <string name="UNO_commands_string_hint">Orden UNO</string>
+ <string name="UNO_commands_string_type_hint">Tipo</string>
+ <string name="UNO_commands_string_value_hint">Valor</string>
+ <string name="action_exportToPDF">Exportar a PDF</string>
+ <string name="action_print">Imprimir</string>
+ <string name="tabhost_character">Carácter</string>
+ <string name="tabhost_paragraph">Párrafo</string>
+ <string name="tabhost_insert">Insertar</string>
+ <string name="tabhost_style">Estilo</string>
+ <string name="alert_ok">Aceptar</string>
+ <string name="alert_cancel">Cancelar</string>
+ <string name="current_uno_command">Orden UNO actual</string>
+ <string name="display_language">Mostrar en idioma</string>
+ <string name="display_language_summary">Establecer el idioma en pantalla predeterminado</string>
+ <string name="pdf_export_finished">Terminó la exportación a PDF</string>
+ <string name="unable_to_export_pdf">No se pudo exportar a PDF</string>
+ <string name="unable_to_save">No se pudo guardar el archivo</string>
+ <string name="error">Error</string>
+ <string name="bmp_null">El BMP está vacío.</string>
+ <string name="page">Página</string>
+ <string name="sheet">Hoja</string>
+ <string name="slide">Diapositiva</string>
+ <string name="part">Parte</string>
+ <string name="highlight_color">Color de resalte</string>
+ <string name="font_color">Color de letra</string>
+ <string name="automatic">Automático</string>
+ <string name="pref_developer_mode_summary">Activar el modo de desarrollo para enviar órdenes UNO mediante la aplicación. Úselo bajo su responsabilidad.</string>
+ <string name="calc_optimal_height">Altura óptima</string>
+ <string name="enter_part_name">Introduzca un nombre para la parte</string>
+ <string name="action_UNO_commands">Enviar orden UNO</string>
+ <string name="action_rename_slide">Cambiar nombre de diapositiva</string>
+ <string name="calc_alert_double_click_optimal_length">Consejo: tocar dos veces una cabecera define la anchura/altura óptima.</string>
+ <string name="calc_optimal_length_default_text">Introduzca la longitud adicional en centésimas de milímetro</string>
+ <string name="UNO_commands_string_parent_value_hint">Valor superior</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-eu/strings.xml b/android/source/res/values-eu/strings.xml
new file mode 100644
index 000000000000..660fce1fb581
--- /dev/null
+++ b/android/source/res/values-eu/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="action_settings">Ezarpenak</string>
+ <string name="action_search">Bilatu</string>
+ <string name="action_undo">Desegin</string>
+ <string name="action_UNO_commands">Bidali UNO komandoa</string>
+ <string name="app_description">LibreOffice ikustailea LibreOffice-n oinarritutako dokumentu-ikustailea da.</string>
+ <string name="app_name">LibreOffice ikustailea</string>
+ <string name="app_version">Bertsioa: %1$s&lt;br&gt;Konpilazioaren IDa: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Kaleratze hau $VENDOR hornitzaileak ekarri du.</string>
+ <string name="about_license">Erakutsi lizentzia</string>
+ <string name="about_notice">Erakutsi oharra</string>
+ <string name="new_textdocument">Testu-dokumentu berria</string>
+ <string name="new_presentation">Aurkezpen berria</string>
+ <string name="new_spreadsheet">Kalkulu-orri berria</string>
+ <string name="new_drawing">Marrazki berria</string>
+ <string name="default_document_name">izengabea</string>
+ <string name="select_file_to_open">Hautatu fitxategia irekitzeko</string>
+ <string name="file_icon_desc">fitxategiaren ikonoa</string>
+ <string name="title_browser">Fitxategi guztiak</string>
+ <string name="pref_category_general">Orokorra</string>
+ <string name="pref_experimental_editing">Modu esperimentala</string>
+ <string name="pref_developer_mode">Garapen modua</string>
+ <string name="pref_developer_mode_summary">Gaitu garapen modua UNO komandoak aplikazioan bidaltzeko. Erabili zure arriskupean.</string>
+ <string name="title_recents">Azken fitxategiak</string>
+ <string name="about_privacy_policy">Pribatutasun-politika</string>
+ <string name="create_file">Sortu fitxategi berria</string>
+ <string name="search_find_next">Aurkitu hurrengoa</string>
+ <string name="search_find_previous">Aurkitu aurrekoa</string>
+ <string name="action_parts">Zatiak</string>
+ <string name="action_keyboard">Erakutsi teklatua</string>
+ <string name="action_save">Gorde</string>
+ <string name="action_save_as">Gorde honela…</string>
+ <string name="action_fromat">Gaitu formatua</string>
+ <string name="message_saved">Gorde da</string>
+ <string name="message_saving">Dokumentua gordetzen…</string>
+ <string name="message_saving_failed">Ezin izan da gorde dokumentua.</string>
+ <string name="password">Pasahitza</string>
+ <string name="action_redo">Berregin</string>
+ <string name="save_document">GORDE</string>
+ <string name="action_cancel">Utzi</string>
+ <string name="no_save_document">EZ</string>
+ <string name="action_add_slide">Gehitu diapositiba</string>
+ <string name="action_presentation">Diapositiba-saioa</string>
+ <string name="slideshow_action_back">Itzuli</string>
+ <string name="calc_insert_before">Txertatu</string>
+ <string name="calc_delete">Ezabatu</string>
+ <string name="calc_hide">Ezkutatu</string>
+ <string name="calc_show">Erakutsi</string>
+ <string name="calc_adjust_length">Doitu luzera</string>
+ <string name="calc_adjust_height">Doitu altuera</string>
+ <string name="calc_adjust_width">Doitu zabalera</string>
+ <string name="calc_optimal_height">Altuera egokia</string>
+ <string name="calc_optimal_width">Zabalera egokia</string>
+ <string name="calc_optimal_length_confirm">Ados</string>
+ <string name="calc_alert_double_click_optimal_length">Aholkua: Goiburuan birritan sakatzean zabalera/altuera egokia ezartzen du.</string>
+ <string name="action_add_worksheet">Gehitu laneko orria</string>
+ <string name="action_pwd_dialog_OK">Ados</string>
+ <string name="action_pwd_dialog_cancel">Utzi</string>
+ <string name="action_pwd_dialog_title">Sartu pasahitza</string>
+ <string name="take_photo">Atera argazkia</string>
+ <string name="select_photo">Hautatu argazkia</string>
+ <string name="select_photo_title">Hautatu irudia</string>
+ <string name="no_camera_found">Ez da aurkitu kamerarik</string>
+ <string name="compress_photo_smallest_size">Tamaina txikiena</string>
+ <string name="compress_photo_medium_size">Tamaina ertaina</string>
+ <string name="compress_photo_max_quality">Gehieneko kalitatea</string>
+ <string name="compress_photo_no_compress">Ez konprimatu</string>
+ <string name="compress_photo_title">Argazkia konprimatu nahi duzu\?</string>
+ <string name="action_copy">Kopiatu</string>
+ <string name="action_paste">Itsatsi</string>
+ <string name="action_cut">Moztu</string>
+ <string name="action_back">Itzuli</string>
+ <string name="action_text_copied">Testua arbelera kopiatu da</string>
+ <string name="insert_table">Txertatu taula</string>
+ <string name="select_insert_options">Hautatu txertatzeko aukerak:</string>
+ <string name="select_delete_options">Hautatu ezabatzeko aukerak:</string>
+ <string name="action_rename_worksheet">Aldatu laneko orriaren izena</string>
+ <string name="action_delete_worksheet">Ezabatu laneko orria</string>
+ <string name="action_delete_slide">Ezabatu diapositiba</string>
+ <string name="name_already_used">Emandako izena erabilia dago jada.</string>
+ <string name="part_name_changed">Zatiaren izena aldatu da.</string>
+ <string name="part_deleted">Zatia ezabatu da.</string>
+ <string name="UNO_commands_string_value_hint">Balioa</string>
+ <string name="UNO_commands_string_parent_value_hint">Balio nagusia</string>
+ <string name="tabhost_style">Estiloa</string>
+ <string name="alert_ok">Ados</string>
+ <string name="alert_cancel">Utzi</string>
+ <string name="current_uno_command">Uneko UNO komandoa</string>
+ <string name="display_language">Bistaratzeko hizkuntza</string>
+ <string name="display_language_summary">Ezarri bistaratzeko hizkuntza lehenetsia</string>
+ <string name="pdf_export_finished">PDF-a esportatu da</string>
+ <string name="unable_to_export_pdf">Ezin izan da esportatu PDF-ra</string>
+ <string name="unable_to_save">Ezin izan da gorde fitxategia</string>
+ <string name="error">Errorea</string>
+ <string name="enter_part_name">Sartu zatiaren izena</string>
+ <string name="bmp_null">Bmp nulua da.</string>
+ <string name="page">Orria</string>
+ <string name="sheet">Orria</string>
+ <string name="slide">Diapositiba</string>
+ <string name="part">Zatia</string>
+ <string name="highlight_color">Nabarmendutako kolorea</string>
+ <string name="font_color">Letra-tipoaren kolorea</string>
+ <string name="action_rename_slide">Aldatu diapositibaren izena</string>
+ <string name="automatic">Automatikoa</string>
+ <string name="app_name_settings">LibreOffice ikustailearen ezarpenak</string>
+ <string name="readonly_file">Fitxategi hau irakurtzeko soilik da.</string>
+ <string name="pref_experimental_editing_summary">Gaitu edizio modu esperimentala. Erabili zure arriskupean.</string>
+ <string name="action_about">Honi buruz</string>
+ <string name="save_alert_dialog_title">Dokumentua gorde nahi duzu itxi aurretik\?</string>
+ <string name="calc_optimal_length">Luzera egokia</string>
+ <string name="calc_optimal_length_default_text">Sartu luzera gehigarria 100th/mm neurrian</string>
+ <string name="UNO_commands_string_type_hint">Mota</string>
+ <string name="tabhost_paragraph">Paragrafoa</string>
+ <string name="UNO_commands_string_hint">UNO komandoa</string>
+ <string name="action_exportToPDF">Esportatu PDF-ra</string>
+ <string name="action_print">Inprimatu</string>
+ <string name="tabhost_character">Karakterea</string>
+ <string name="tabhost_insert">Txertatu</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-fa/strings.xml b/android/source/res/values-fa/strings.xml
new file mode 100644
index 000000000000..b307d00eeed2
--- /dev/null
+++ b/android/source/res/values-fa/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name_settings">تنظیمات نمایشگر لیبره آفیس</string>
+ <string name="app_name">نمایشگر لیبره آفیس</string>
+ <string name="app_version">نسخه: %1$s&lt;br&gt;شناسه ساخت: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">نمایشگر لیبره آفیس یک نمایشگر سند مبتنی بر لیبره آفیس است.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">این نسخه توسط $VENDOR ارائه شده است.</string>
+ <string name="readonly_file">این پرونده فقط خواندنی است.</string>
+ <string name="select_file_to_open">پرونده را برای باز کردن انتخاب کنید</string>
+ <string name="search_find_next">یافتن بعدی</string>
+ <string name="action_about">درباره</string>
+ <string name="action_parts">اجزاء</string>
+ <string name="action_settings">تنظیمات</string>
+ <string name="pref_developer_mode">حالت برنامه‌نویس</string>
+ <string name="pref_developer_mode_summary">حالت برنامه‌نویس را فعال کنید تا بتوانید دستورات UNO را در برنامه ارسال کنید. با مسئولیت خودتان استفاده کنید.</string>
+ <string name="action_UNO_commands">ارسال دستور UNO</string>
+ <string name="message_saved">ذخیره کردن کامل شد</string>
+ <string name="message_saving">ذخیره کردن سند…</string>
+ <string name="slideshow_action_back">بازگشت</string>
+ <string name="action_delete_slide">حذف اسلاید</string>
+ <string name="error">خطا</string>
+ <string name="action_save_as">ذخیره به عنوان…</string>
+ <string name="new_textdocument">سند متنی جدید</string>
+ <string name="new_presentation">ارائه جدید</string>
+ <string name="new_spreadsheet">صفحه گسترده جدید</string>
+ <string name="new_drawing">طراحی جدید</string>
+ <string name="default_document_name">بدون عنوان</string>
+ <string name="file_icon_desc">شمایل پرونده</string>
+ <string name="title_browser">همه پرونده‌ها</string>
+ <string name="pref_category_general">عمومی</string>
+ <string name="pref_experimental_editing">حالت آزمایشی</string>
+ <string name="action_keyboard">نمایش صفحه کلید</string>
+ <string name="action_save">ذخیره</string>
+ <string name="about_privacy_policy">سیاست حریم خصوصی</string>
+ <string name="create_file">ایجاد پرونده جدید</string>
+ <string name="search_find_previous">یافتن قبلی</string>
+ <string name="action_search">جستجو</string>
+ <string name="message_saving_failed">ذخیره کردن سند ناموفق بود.</string>
+ <string name="password">رمز عبور</string>
+ <string name="action_undo">واگردان</string>
+ <string name="save_alert_dialog_title">آیا سند قبل از بستن ذخیره شود؟</string>
+ <string name="save_document">ذخیره</string>
+ <string name="action_cancel">لغو</string>
+ <string name="no_save_document">خیر</string>
+ <string name="action_add_slide">افزودن اسلاید</string>
+ <string name="calc_insert_before">درج</string>
+ <string name="calc_delete">حذف</string>
+ <string name="calc_hide">پنهان کردن</string>
+ <string name="calc_show">نمایش</string>
+ <string name="calc_optimal_length">طول بهینه</string>
+ <string name="calc_adjust_length">تنظیم طول</string>
+ <string name="calc_adjust_height">تنظیم ارتفاع</string>
+ <string name="calc_adjust_width">تنظیم عرض</string>
+ <string name="calc_optimal_width">عرض بهینه</string>
+ <string name="calc_optimal_length_confirm">باشد</string>
+ <string name="calc_optimal_length_default_text">طول اضافی را در واحد 100 تا در میلی‌متر وارد کنید</string>
+ <string name="action_add_worksheet">افزودن کاربرگ</string>
+ <string name="action_pwd_dialog_OK">باشد</string>
+ <string name="action_pwd_dialog_cancel">لغو</string>
+ <string name="action_pwd_dialog_title">لطفاً رمز عبور را وارد کنید</string>
+ <string name="take_photo">عکس گرفتن</string>
+ <string name="select_photo">انتخاب عکس</string>
+ <string name="select_photo_title">انتخاب تصویر</string>
+ <string name="no_camera_found">هیچ دوربینی یافت نشد</string>
+ <string name="compress_photo_smallest_size">کوچک‌ترین اندازه</string>
+ <string name="compress_photo_medium_size">اندازه متوسط</string>
+ <string name="compress_photo_no_compress">فشرده نکن</string>
+ <string name="action_paste">چسباندن</string>
+ <string name="action_cut">برش</string>
+ <string name="action_back">بازگشت</string>
+ <string name="insert_table">درج جدول</string>
+ <string name="select_delete_options">گزینه‌های حذف را انتخاب کنید:</string>
+ <string name="action_rename_worksheet">تغییر نام کاربرگ</string>
+ <string name="action_delete_worksheet">حذف کاربرگ</string>
+ <string name="name_already_used">نام داده شده پیش از این در حال استفاده است.</string>
+ <string name="part_name_changed">نام جزء تغییر کرده است.</string>
+ <string name="part_deleted">جزء حذف شده است.</string>
+ <string name="UNO_commands_string_hint">دستور UNO</string>
+ <string name="UNO_commands_string_type_hint">نوع</string>
+ <string name="UNO_commands_string_value_hint">مقدار</string>
+ <string name="UNO_commands_string_parent_value_hint">مقدار والد</string>
+ <string name="action_print">چاپ</string>
+ <string name="tabhost_character">نویسه</string>
+ <string name="tabhost_paragraph">بند</string>
+ <string name="tabhost_insert">درج</string>
+ <string name="tabhost_style">سبک</string>
+ <string name="alert_ok">باشد</string>
+ <string name="alert_cancel">لغو</string>
+ <string name="current_uno_command">دستورات UNO فعلی</string>
+ <string name="display_language">زبان نمایش</string>
+ <string name="pdf_export_finished">صدور به PDF پایان یافت</string>
+ <string name="unable_to_export_pdf">صدور به PDF ممکن نبود</string>
+ <string name="unable_to_save">ذخیره پرونده ممکن نبود</string>
+ <string name="enter_part_name">نام یک جزء را وارد کنید</string>
+ <string name="bmp_null">Bmp تهی است!</string>
+ <string name="page">صفحه</string>
+ <string name="sheet">برگه</string>
+ <string name="part">جزء</string>
+ <string name="highlight_color">رنگ برجسته کردن</string>
+ <string name="action_rename_slide">تغییر نام اسلاید</string>
+ <string name="automatic">خودکار</string>
+ <string name="action_fromat">فعال کردن قالب</string>
+ <string name="about_license">نمایش اجازه‌نامه‌ها</string>
+ <string name="about_notice">نمایش اطلاعیه</string>
+ <string name="title_recents">پرونده‌های اخیر</string>
+ <string name="pref_experimental_editing_summary">حالت آزمایشی ویرایش را فعال کنید. با مسئولیت خودتان استفاده کنید.</string>
+ <string name="action_redo">انجام دوباره</string>
+ <string name="action_presentation">نمایش اسلاید</string>
+ <string name="calc_optimal_height">ارتفاع بهینه</string>
+ <string name="compress_photo_max_quality">کیفیت بیشینه</string>
+ <string name="calc_alert_double_click_optimal_length">نکته: دوبار ضربه زدن روی سرایند عرض/ارتفاع بهینه را تنظیم می‌کند.</string>
+ <string name="compress_photo_title">آیا می‌خواهید عکس را فشرده کنید؟</string>
+ <string name="action_copy">کپی</string>
+ <string name="slide">اسلاید</string>
+ <string name="action_text_copied">متن در تخته کپی شد</string>
+ <string name="select_insert_options">گزینه‌های درج را انتخاب کنید:</string>
+ <string name="action_exportToPDF">صدور به PDF</string>
+ <string name="display_language_summary">زبان نمایش پیش‌فرض را تنظیم کنید</string>
+ <string name="font_color">رنگ قلم</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-fi/strings.xml b/android/source/res/values-fi/strings.xml
new file mode 100644
index 000000000000..a6b3daec9354
--- /dev/null
+++ b/android/source/res/values-fi/strings.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources></resources> \ No newline at end of file
diff --git a/android/source/res/values-fr/strings.xml b/android/source/res/values-fr/strings.xml
new file mode 100644
index 000000000000..48f8f56ec0c5
--- /dev/null
+++ b/android/source/res/values-fr/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name_settings">Paramètre de l\'afficheur LibreOffice</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Cette version est fournie par $VENDOR.</string>
+ <string name="readonly_file">Ce fichier est en lecture seule.</string>
+ <string name="about_license">Afficher la licence</string>
+ <string name="about_notice">Afficher la notice</string>
+ <string name="app_version">Version : %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">LibreOffice Viewer est une visionneuse de document basée sur LibreOffice.</string>
+ <string name="search_find_next">Rechercher le suivant</string>
+ <string name="search_find_previous">Rechercher le précédent</string>
+ <string name="file_icon_desc">fileicon</string>
+ <string name="title_recents">Fichiers récents</string>
+ <string name="title_browser">Tous les fichiers</string>
+ <string name="pref_category_general">Général</string>
+ <string name="create_file">Créer un nouveau fichier</string>
+ <string name="new_textdocument">Nouveau document texte</string>
+ <string name="new_presentation">Nouvelle présentation</string>
+ <string name="new_spreadsheet">Nouveau classeur</string>
+ <string name="new_drawing">Nouveau dessin</string>
+ <string name="default_document_name">sans titre</string>
+ <string name="select_file_to_open">Sélectionner un fichier à ouvrir</string>
+ <string name="pref_experimental_editing">Mode expérimental</string>
+ <string name="action_add_slide">Ajouter une diapo</string>
+ <string name="slideshow_action_back">Précédent</string>
+ <string name="calc_insert_before">Insérer</string>
+ <string name="calc_delete">Supprimer</string>
+ <string name="calc_hide">Masquer</string>
+ <string name="calc_show">Afficher</string>
+ <string name="calc_optimal_length">Longueur optimale</string>
+ <string name="calc_adjust_height">Adapter la hauteur</string>
+ <string name="calc_adjust_width">Adapter la largeur</string>
+ <string name="calc_optimal_height">Hauteur optimale</string>
+ <string name="calc_optimal_width">Largeur optimale</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="about_privacy_policy">Politique de confidentialité</string>
+ <string name="action_presentation">Diaporama</string>
+ <string name="calc_adjust_length">Adapter la longueur</string>
+ <string name="action_UNO_commands">Envoyer Cmd UNO</string>
+ <string name="message_saved">Enregistrement terminé</string>
+ <string name="message_saving">Enregistrement du document…</string>
+ <string name="action_keyboard">Afficher le clavier</string>
+ <string name="action_save">Enregistrer</string>
+ <string name="action_fromat">Activer le formatage</string>
+ <string name="action_search">Rechercher</string>
+ <string name="action_add_worksheet">Ajouter une feuille de calcul</string>
+ <string name="action_exportToPDF">Exporter au format PDF</string>
+ <string name="action_print">Imprimer</string>
+ <string name="page">Page</string>
+ <string name="action_save_as">Enregistrer sous…</string>
+ <string name="pref_experimental_editing_summary">Activez le mode d\'édition expérimental. À utiliser à vos risques et périls.</string>
+ <string name="pref_developer_mode">Mode développeur</string>
+ <string name="action_settings">Paramètres</string>
+ <string name="message_saving_failed">L\'enregistrement du document a échoué</string>
+ <string name="pref_developer_mode_summary">Activez le mode développeur où vous pouvez envoyer des commandes UNO dans l\'application. À utiliser à vos risques et périls.</string>
+ <string name="action_about">À propos</string>
+ <string name="action_parts">Parties</string>
+ <string name="password">Mot de passe</string>
+ <string name="action_undo">Annuler</string>
+ <string name="action_redo">Rétablir</string>
+ <string name="save_alert_dialog_title">Enregistrer le document avant de le fermer \?</string>
+ <string name="save_document">ENREGISTRER</string>
+ <string name="action_cancel">Annuler</string>
+ <string name="no_save_document">NON</string>
+ <string name="calc_optimal_length_default_text">Saisissez la longueur supplémentaire en 100ème/mm</string>
+ <string name="calc_alert_double_click_optimal_length">Astuce : appuyez deux fois sur un en-tête pour définir la largeur/hauteur optimale.</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="action_pwd_dialog_cancel">Annuler</string>
+ <string name="action_pwd_dialog_title">Veuillez saisir le mot de passe</string>
+ <string name="take_photo">Prendre une photo</string>
+ <string name="select_photo">Sélectionner une photo</string>
+ <string name="select_photo_title">Sélectionner une image</string>
+ <string name="no_camera_found">Aucune caméra trouvée</string>
+ <string name="compress_photo_smallest_size">Plus petite taille</string>
+ <string name="compress_photo_medium_size">Taille moyenne</string>
+ <string name="compress_photo_max_quality">Qualité maximale</string>
+ <string name="compress_photo_no_compress">Ne pas compresser</string>
+ <string name="compress_photo_title">Voulez-vous compresser la photo \?</string>
+ <string name="action_copy">Copier</string>
+ <string name="action_paste">Coller</string>
+ <string name="action_cut">Couper</string>
+ <string name="action_back">Précédent</string>
+ <string name="action_text_copied">Texte copié dans le presse-papiers</string>
+ <string name="insert_table">Insérer un tableau</string>
+ <string name="select_insert_options">Sélectionnez les options d\'insertion :</string>
+ <string name="select_delete_options">Sélectionnez les options de suppression :</string>
+ <string name="action_rename_worksheet">Renommer la feuille de calcul</string>
+ <string name="action_delete_worksheet">Supprimer la feuille de calcul</string>
+ <string name="action_delete_slide">Supprimer la diapo</string>
+ <string name="name_already_used">Le nom donné est déjà utilisé.</string>
+ <string name="part_name_changed">Le nom de la partie a été modifié.</string>
+ <string name="part_deleted">La partie a été supprimée.</string>
+ <string name="UNO_commands_string_hint">Commande UNO</string>
+ <string name="UNO_commands_string_type_hint">Type</string>
+ <string name="UNO_commands_string_value_hint">Valeur</string>
+ <string name="UNO_commands_string_parent_value_hint">Valeur parent</string>
+ <string name="tabhost_character">Caractère</string>
+ <string name="tabhost_paragraph">Paragraphe</string>
+ <string name="tabhost_insert">Insérer</string>
+ <string name="tabhost_style">Style</string>
+ <string name="alert_ok">OK</string>
+ <string name="alert_cancel">Annuler</string>
+ <string name="current_uno_command">Commande UNO actuelle</string>
+ <string name="display_language">Afficher la langue</string>
+ <string name="display_language_summary">Définir la langue d\'affichage par défaut</string>
+ <string name="pdf_export_finished">Export au format PDF terminé</string>
+ <string name="unable_to_export_pdf">Impossible d\'exporter au format PDF</string>
+ <string name="unable_to_save">Impossible d\'enregistrer le fichier</string>
+ <string name="error">Erreur</string>
+ <string name="enter_part_name">Saisissez le nom d\'une partie</string>
+ <string name="bmp_null">Bmp est invalide !</string>
+ <string name="sheet">Feuille</string>
+ <string name="slide">Diapo</string>
+ <string name="part">Partie</string>
+ <string name="highlight_color">Couleur de surlignage</string>
+ <string name="font_color">Couleur de police</string>
+ <string name="action_rename_slide">Renommer la diapo</string>
+ <string name="automatic">Automatique</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-gl/strings.xml b/android/source/res/values-gl/strings.xml
new file mode 100644
index 000000000000..3ad68bd82357
--- /dev/null
+++ b/android/source/res/values-gl/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="calc_optimal_length_default_text">Introduza lonxitude extra en centésimas de milímetro</string>
+ <string name="compress_photo_no_compress">Non comprimir</string>
+ <string name="new_presentation">Nova presentación</string>
+ <string name="app_name">Visor do LibreOffice</string>
+ <string name="calc_adjust_width">Axustar largura</string>
+ <string name="app_name_settings">Configuración do visor do LibreOffice</string>
+ <string name="app_description">O Visor do LibreOffice é un visor de documentos baseado no LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Esta versión foi fornecida por $VENDOR.</string>
+ <string name="readonly_file">Este ficheiro só permite lectura.</string>
+ <string name="about_license">Mostrar licenza</string>
+ <string name="about_notice">Mostrar aviso</string>
+ <string name="about_privacy_policy">Política de privacidade</string>
+ <string name="create_file">Crear novo ficheiro</string>
+ <string name="new_textdocument">Novo documento de texto</string>
+ <string name="new_spreadsheet">Nova folla de cálculo</string>
+ <string name="new_drawing">Novo debuxo</string>
+ <string name="default_document_name">sen título</string>
+ <string name="select_file_to_open">Seleccionar ficheiro para abrir</string>
+ <string name="search_find_previous">Atopar anterior</string>
+ <string name="file_icon_desc">iconadeficheiro</string>
+ <string name="title_recents">Ficheiros recentes</string>
+ <string name="title_browser">Todos os ficheiros</string>
+ <string name="pref_category_general">Xeral</string>
+ <string name="pref_experimental_editing_summary">Activar o modo de edición experimental. Úseo baixo a súa responsabilidade.</string>
+ <string name="pref_developer_mode">Modo de desenvolvemento</string>
+ <string name="action_about">Sobre</string>
+ <string name="action_parts">Partes</string>
+ <string name="action_settings">Configuración</string>
+ <string name="action_save">Gardar</string>
+ <string name="action_save_as">Gardar como…</string>
+ <string name="action_search">Buscar</string>
+ <string name="action_UNO_commands">Enviar orde de UNO</string>
+ <string name="message_saving">Gardar o documento…</string>
+ <string name="message_saving_failed">Fallou o gardado do documento.</string>
+ <string name="action_undo">Desfacer</string>
+ <string name="action_redo">Refacer</string>
+ <string name="save_document">GARDAR</string>
+ <string name="no_save_document">NON</string>
+ <string name="action_presentation">Presentación de diapositivas</string>
+ <string name="action_add_slide">Engadir diapositiva</string>
+ <string name="slideshow_action_back">Atrás</string>
+ <string name="calc_insert_before">Inserir</string>
+ <string name="calc_delete">Eliminar</string>
+ <string name="calc_hide">Agochar</string>
+ <string name="calc_show">Mostrar</string>
+ <string name="calc_optimal_length">Lonxitude ideal</string>
+ <string name="calc_adjust_length">Axustar lonxitude</string>
+ <string name="calc_adjust_height">Axustar altura</string>
+ <string name="calc_optimal_height">Altura ideal</string>
+ <string name="calc_optimal_width">Largura ideal</string>
+ <string name="calc_optimal_length_confirm">Aceptar</string>
+ <string name="action_add_worksheet">Engadir folla de cálculo</string>
+ <string name="action_pwd_dialog_OK">Aceptar</string>
+ <string name="action_pwd_dialog_cancel">Cancelar</string>
+ <string name="take_photo">Tirar foto</string>
+ <string name="select_photo">Seleccionar foto</string>
+ <string name="no_camera_found">Non se atopou ningunha cámara</string>
+ <string name="compress_photo_smallest_size">Tamaño menor</string>
+ <string name="compress_photo_medium_size">Tamaño mediano</string>
+ <string name="compress_photo_max_quality">Calidade máxima</string>
+ <string name="compress_photo_title">Desexa comprimir a foto\?</string>
+ <string name="action_copy">Copiar</string>
+ <string name="action_paste">Pegar</string>
+ <string name="action_cut">Cortar</string>
+ <string name="insert_table">Inserir táboa</string>
+ <string name="select_insert_options">Seleccionar opcións de inserción:</string>
+ <string name="select_delete_options">Seleccionar opcións de eliminación:</string>
+ <string name="action_rename_worksheet">Renomear folla de cálculo</string>
+ <string name="action_delete_slide">Eliminar diapositiva</string>
+ <string name="name_already_used">O nome dado xa está en uso.</string>
+ <string name="part_name_changed">O nome da parte cambiou.</string>
+ <string name="part_deleted">A parte foi eliminada.</string>
+ <string name="UNO_commands_string_hint">Orde de UNO</string>
+ <string name="UNO_commands_string_type_hint">Tipo</string>
+ <string name="UNO_commands_string_value_hint">Valor</string>
+ <string name="UNO_commands_string_parent_value_hint">Valor superior</string>
+ <string name="action_exportToPDF">Exportar a PDF</string>
+ <string name="action_print">Imprimir</string>
+ <string name="search_find_next">Atopar seguinte</string>
+ <string name="tabhost_character">Carácter</string>
+ <string name="tabhost_paragraph">Parágrafo</string>
+ <string name="tabhost_insert">Inserir</string>
+ <string name="tabhost_style">Estilo</string>
+ <string name="alert_ok">Aceptar</string>
+ <string name="alert_cancel">Cancelar</string>
+ <string name="current_uno_command">Orde de UNO actual</string>
+ <string name="display_language">Idioma para mostrar</string>
+ <string name="display_language_summary">Configurar o idioma predeterminado</string>
+ <string name="pdf_export_finished">Rematou a exportación a PDF</string>
+ <string name="unable_to_export_pdf">Non foi posíbel exportar a pdf</string>
+ <string name="unable_to_save">Non foi posíbel gardar o ficheiro</string>
+ <string name="error">Erro</string>
+ <string name="enter_part_name">Introduza un nome da parte</string>
+ <string name="bmp_null">BMP é nulo!</string>
+ <string name="page">Páxina</string>
+ <string name="sheet">Folla</string>
+ <string name="slide">Diapositiva</string>
+ <string name="part">Parte</string>
+ <string name="highlight_color">Cor de realce</string>
+ <string name="font_color">Cor do tipo de letra</string>
+ <string name="action_rename_slide">Renomear diapositiva</string>
+ <string name="automatic">Automático</string>
+ <string name="app_version">Versión: %1$s&lt;br&gt;Identificador da construción: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="action_keyboard">Mostrar teclado</string>
+ <string name="action_fromat">Activar formato</string>
+ <string name="action_text_copied">Texto copiado ao portapapeis</string>
+ <string name="pref_experimental_editing">Modo experimental</string>
+ <string name="pref_developer_mode_summary">Activar modo de desenvolvemento, no que se poden enviar ordes de UNO dentro da app. Úseo baixo a súa responsabilidade.</string>
+ <string name="message_saved">Gardar completo</string>
+ <string name="password">Contrasinal</string>
+ <string name="save_alert_dialog_title">Gardar o documento antes de pechar\?</string>
+ <string name="action_cancel">Cancelar</string>
+ <string name="calc_alert_double_click_optimal_length">Suxestión: Tocar dúas veces nunha cabeceira estabelece a largura/altura ideais.</string>
+ <string name="action_pwd_dialog_title">Introduza contrasinal</string>
+ <string name="select_photo_title">Seleccionar imaxe</string>
+ <string name="action_back">Atrás</string>
+ <string name="action_delete_worksheet">Eliminar folla de cálculo</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-hsb/strings.xml b/android/source/res/values-hsb/strings.xml
new file mode 100644
index 000000000000..e8feed7dd991
--- /dev/null
+++ b/android/source/res/values-hsb/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_version">Wersija: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Tute wozjewjenje je so wot $VENDOR k dispoziciji stajiło.</string>
+ <string name="readonly_file">Tuta dataja je přećiwo pisanju škitana.</string>
+ <string name="about_notice">Zdźělenku pokazać</string>
+ <string name="create_file">Nowu dataju wutworić</string>
+ <string name="new_textdocument">Nowy tekstowy dokument</string>
+ <string name="new_presentation">Nowa prezentacija</string>
+ <string name="new_spreadsheet">Nowy tabelowy dokument</string>
+ <string name="new_drawing">Nowa rysowanka</string>
+ <string name="default_document_name">bjez titula</string>
+ <string name="select_file_to_open">Wubjerće dataju, kotraž so ma wočinić</string>
+ <string name="search_find_next">Dale pytać</string>
+ <string name="file_icon_desc">datajowy symbol</string>
+ <string name="title_recents">Najnowše dataje</string>
+ <string name="title_browser">Wšě dataje</string>
+ <string name="pref_category_general">Powšitkowne</string>
+ <string name="pref_experimental_editing">Eksperimentelny modus</string>
+ <string name="pref_developer_mode">Wuwiwarski modus</string>
+ <string name="pref_developer_mode_summary">Wuwiwarski modus zmóžnić, hdźež móžeće přikazy UNO w nałoženju pósłać. Wužiwanje na swójske riziko.</string>
+ <string name="action_about">Wo</string>
+ <string name="action_parts">Dźěle</string>
+ <string name="action_settings">Nastajenja</string>
+ <string name="action_keyboard">Tastaturu pokazać</string>
+ <string name="action_save">Składować</string>
+ <string name="action_save_as">Składować jako…</string>
+ <string name="action_fromat">Format zmóžnić</string>
+ <string name="action_search">Pytać</string>
+ <string name="message_saved">Składowanje dokónčene</string>
+ <string name="message_saving">Dokument so składuje…</string>
+ <string name="password">Hesło</string>
+ <string name="action_undo">Cofnyć</string>
+ <string name="action_redo">Wospjetować</string>
+ <string name="save_alert_dialog_title">Dokument do začinjenja składować\?</string>
+ <string name="save_document">SKŁADOWAĆ</string>
+ <string name="action_cancel">Přetorhnyć</string>
+ <string name="no_save_document">NĚ</string>
+ <string name="action_presentation">Prezentacija</string>
+ <string name="action_add_slide">Foliju přidać</string>
+ <string name="slideshow_action_back">Wróćo</string>
+ <string name="calc_delete">Zhašeć</string>
+ <string name="calc_show">Pokazać</string>
+ <string name="calc_optimal_length">Optimalna dołhosć</string>
+ <string name="calc_adjust_length">Dołhosć přiměrić</string>
+ <string name="calc_adjust_height">Wysokosć přiměrić</string>
+ <string name="calc_adjust_width">Šěrokosć přiměrić</string>
+ <string name="calc_optimal_height">Optimalna wysokosć</string>
+ <string name="calc_optimal_width">Optimalna šěrokosć</string>
+ <string name="calc_optimal_length_confirm">W porjadku</string>
+ <string name="calc_optimal_length_default_text">Zapodajće přidatnu dołhosć w 100tych mm</string>
+ <string name="calc_alert_double_click_optimal_length">Pokiw: Podótkńće so dwójce nadpisma, zo byšće optimalnu šěrokosć/wysokosć nastajił.</string>
+ <string name="action_add_worksheet">Dźěłowe łopjeno přidać</string>
+ <string name="action_pwd_dialog_OK">W porjadku</string>
+ <string name="action_pwd_dialog_cancel">Přetorhnyć</string>
+ <string name="action_pwd_dialog_title">Zapodajće prošu hesło</string>
+ <string name="select_photo">Foto wubrać</string>
+ <string name="select_photo_title">Wobraz wubrać</string>
+ <string name="no_camera_found">Žana kamera namakana</string>
+ <string name="compress_photo_smallest_size">Najmjeńša wulkosć</string>
+ <string name="compress_photo_max_quality">Maksimalna kwalita</string>
+ <string name="compress_photo_title">Chceće foto komprimować\?</string>
+ <string name="action_copy">Kopěrować</string>
+ <string name="action_paste">Zasadźić</string>
+ <string name="action_cut">Wutřihać</string>
+ <string name="action_back">Wróćo</string>
+ <string name="action_text_copied">Tekst je so do mjezyskłada kopěrował</string>
+ <string name="insert_table">Tabelu zasadźić</string>
+ <string name="select_insert_options">Zasadźenske nastajenja wubrać:</string>
+ <string name="action_rename_worksheet">Dźěłowe łopjeno přemjenować</string>
+ <string name="action_delete_worksheet">Dźěłowe łopjeno zhašeć</string>
+ <string name="action_delete_slide">Foliju zhašeć</string>
+ <string name="name_already_used">Podate mjeno so hižo wužiwa.</string>
+ <string name="part_name_changed">Mjeno dźěla je so změniło.</string>
+ <string name="part_deleted">Dźěl je so zhašał.</string>
+ <string name="UNO_commands_string_type_hint">Typ</string>
+ <string name="UNO_commands_string_value_hint">Hódnota</string>
+ <string name="UNO_commands_string_parent_value_hint">Nadrjadowana hódnota</string>
+ <string name="action_exportToPDF">Jako PDF eksportować</string>
+ <string name="action_print">Ćišćeć</string>
+ <string name="tabhost_character">Znamješko</string>
+ <string name="tabhost_paragraph">Wotstawk</string>
+ <string name="tabhost_insert">Zasadźić</string>
+ <string name="tabhost_style">Předłoha</string>
+ <string name="alert_ok">W porjadku</string>
+ <string name="alert_cancel">Přetorhnyć</string>
+ <string name="current_uno_command">Aktualny přikaz UNO</string>
+ <string name="display_language">Pokazowanska rěč</string>
+ <string name="display_language_summary">Nastajće standardnu pokazowansku rěč</string>
+ <string name="pdf_export_finished">Eksport jako PDF dokónčeny</string>
+ <string name="unable_to_export_pdf">Eksport jako PDF móžny njeje</string>
+ <string name="unable_to_save">Dataja njeda so składować</string>
+ <string name="error">Zmylk</string>
+ <string name="enter_part_name">Mjeno dźěla zapodać</string>
+ <string name="bmp_null">Bmp je nul!</string>
+ <string name="page">Strona</string>
+ <string name="sheet">Tabela</string>
+ <string name="slide">Folija</string>
+ <string name="part">Dźěl</string>
+ <string name="highlight_color">Wuzběhnjenska barba</string>
+ <string name="font_color">Pismowa barba</string>
+ <string name="action_rename_slide">Foliju přemjenować</string>
+ <string name="automatic">Awtomatiski</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="app_name_settings">Nastajenja LibreOffice Viewer</string>
+ <string name="app_description">LibreOffice Viewer je dokumentowy wobhladowak, kotryž na LibreOffice bazuje.</string>
+ <string name="about_license">Licencu pokazać</string>
+ <string name="about_privacy_policy">Prawidła priwatnosće</string>
+ <string name="search_find_previous">Předchadny pytać</string>
+ <string name="pref_experimental_editing_summary">Eksperimentelny wobdźěłanski modus zmóžnić. Wužiwanje na swójske riziko.</string>
+ <string name="action_UNO_commands">Přikaz UNO pósłać</string>
+ <string name="message_saving_failed">Składowanje dokumenta je so nimokuliło.</string>
+ <string name="calc_insert_before">Zasadźić</string>
+ <string name="calc_hide">Schować</string>
+ <string name="take_photo">Foto činić</string>
+ <string name="compress_photo_medium_size">Srjedźna wulkosć</string>
+ <string name="compress_photo_no_compress">Njekomprimować</string>
+ <string name="select_delete_options">Zhašenske nastajenja wubrać:</string>
+ <string name="UNO_commands_string_hint">Přikaz UNO</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-hu/strings.xml b/android/source/res/values-hu/strings.xml
new file mode 100644
index 000000000000..49ef9910e435
--- /dev/null
+++ b/android/source/res/values-hu/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="pref_developer_mode_summary">Fejlesztői mód engedélyezése, ahol UNO parancsokat küldhet az alkalmazásnak. Saját felelősségre használja.</string>
+ <string name="app_description">A LibreOffice Viewer egy LibreOffice-alapú dokumentummegjelenítő.</string>
+ <string name="calc_show">Megjelenítés</string>
+ <string name="pref_developer_mode">Fejlesztői mód</string>
+ <string name="create_file">Új fájl létrehozása</string>
+ <string name="calc_hide">Elrejtés</string>
+ <string name="action_UNO_commands">UNO parancs küldése</string>
+ <string name="default_document_name">névtelen</string>
+ <string name="action_about">Névjegy</string>
+ <string name="action_fromat">Formázás engedélyezése</string>
+ <string name="password">Jelszó</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="slideshow_action_back">Vissza</string>
+ <string name="save_document">MENTÉS</string>
+ <string name="calc_adjust_length">Hossz igazítása</string>
+ <string name="new_spreadsheet">Új táblázat</string>
+ <string name="select_file_to_open">Fájl kiválasztása</string>
+ <string name="action_save_as">Mentés másként…</string>
+ <string name="save_alert_dialog_title">Bezárás előtt menti a dokumentumot\?</string>
+ <string name="message_saving_failed">A dokumentum mentése meghiúsult.</string>
+ <string name="calc_optimal_length">Optimális hossz</string>
+ <string name="new_drawing">Új rajz</string>
+ <string name="action_redo">Újra</string>
+ <string name="file_icon_desc">fájl ikon</string>
+ <string name="title_recents">Legutóbbi fájlok</string>
+ <string name="calc_insert_before">Beszúrás</string>
+ <string name="message_saving">Dokumentum mentése…</string>
+ <string name="calc_optimal_width">Optimális szélesség</string>
+ <string name="no_save_document">NEM</string>
+ <string name="new_textdocument">Új szöveges dokumentum</string>
+ <string name="calc_adjust_width">Szélesség igazítása</string>
+ <string name="new_presentation">Új bemutató</string>
+ <string name="pref_experimental_editing">Kísérleti mód</string>
+ <string name="calc_delete">Törlés</string>
+ <string name="action_undo">Vissza</string>
+ <string name="app_vendor">A kiadást készítette: $VENDOR.</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="action_parts">Részek</string>
+ <string name="pref_category_general">Általános</string>
+ <string name="action_keyboard">Billentyűzet megjelenítése</string>
+ <string name="about_privacy_policy">Adatvédelem</string>
+ <string name="action_presentation">Diavetítés</string>
+ <string name="action_search">Keresés</string>
+ <string name="message_saved">Mentés kész</string>
+ <string name="app_name_settings">LibreOffice Viewer beállításai</string>
+ <string name="action_save">Mentés</string>
+ <string name="action_settings">Beállítások</string>
+ <string name="app_version">Verzió: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_license">Licenc megjelenítése</string>
+ <string name="title_browser">Minden fájl</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="action_add_slide">Dia hozzáadása</string>
+ <string name="action_cancel">Mégse</string>
+ <string name="calc_adjust_height">Magasság igazítása</string>
+ <string name="search_find_next">Következő találat</string>
+ <string name="search_find_previous">Előző találat</string>
+ <string name="pref_experimental_editing_summary">Kísérleti szerkesztőmód bekapcsolása. Saját felelősségre használja.</string>
+ <string name="readonly_file">A fájl csak olvasható.</string>
+ <string name="about_notice">Megjegyzés megjelenítése</string>
+ <string name="calc_optimal_height">Optimális magasság</string>
+ <string name="pdf_export_finished">PDF export kész</string>
+ <string name="action_pwd_dialog_cancel">Mégse</string>
+ <string name="slide">Dia</string>
+ <string name="part_name_changed">Rész neve módosítva.</string>
+ <string name="compress_photo_max_quality">Max minőség</string>
+ <string name="select_insert_options">Válasszon beszúrási lehetőséget:</string>
+ <string name="UNO_commands_string_type_hint">Típus</string>
+ <string name="current_uno_command">Jelenlegi UNO parancs</string>
+ <string name="bmp_null">A BMP null!</string>
+ <string name="action_paste">Beillesztés</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="part">Rész</string>
+ <string name="unable_to_export_pdf">Nem lehet exportálni PDF-be</string>
+ <string name="font_color">Betűszín</string>
+ <string name="action_rename_worksheet">Munkalap átnevezése</string>
+ <string name="enter_part_name">Írjon be egy résznevet</string>
+ <string name="automatic">Automatikus</string>
+ <string name="action_delete_slide">Dia törlése</string>
+ <string name="action_cut">Kivágás</string>
+ <string name="page">Oldal</string>
+ <string name="calc_optimal_length_default_text">Extra hossz megadása 1/100 mm-ben</string>
+ <string name="tabhost_style">Stílus</string>
+ <string name="select_photo_title">Kép kiválasztása</string>
+ <string name="action_delete_worksheet">Munkalap törlése</string>
+ <string name="highlight_color">Kiemelési szín</string>
+ <string name="action_print">Nyomtatás</string>
+ <string name="action_add_worksheet">Munkalap hozzáadása</string>
+ <string name="tabhost_paragraph">Bekezdés</string>
+ <string name="action_back">Vissza</string>
+ <string name="part_deleted">Rész törölve.</string>
+ <string name="action_pwd_dialog_title">Írja be a jelszót</string>
+ <string name="compress_photo_medium_size">Közepes méret</string>
+ <string name="display_language_summary">Alapértelmezett nyelv beállítása</string>
+ <string name="select_delete_options">Válasszon törlési lehetőségeket:</string>
+ <string name="action_text_copied">Szöveg vágólapra másolva</string>
+ <string name="action_exportToPDF">PDF-be exportálás</string>
+ <string name="action_rename_slide">Dia átnevezése</string>
+ <string name="UNO_commands_string_parent_value_hint">Szülő érték</string>
+ <string name="compress_photo_smallest_size">Legkisebb méret</string>
+ <string name="select_photo">Fénykép kiválasztása</string>
+ <string name="compress_photo_no_compress">Ne tömörítse</string>
+ <string name="action_copy">Másolás</string>
+ <string name="tabhost_insert">Beszúrás</string>
+ <string name="no_camera_found">Nem található kamera</string>
+ <string name="error">Hiba</string>
+ <string name="name_already_used">Ez a név már használatban van.</string>
+ <string name="UNO_commands_string_hint">UNO parancs</string>
+ <string name="alert_ok">OK</string>
+ <string name="UNO_commands_string_value_hint">Érték</string>
+ <string name="sheet">Munkalap</string>
+ <string name="compress_photo_title">Szeretné tömöríteni a fényképet\?</string>
+ <string name="take_photo">Fényképezés</string>
+ <string name="unable_to_save">Nem lehet menteni a fájlt</string>
+ <string name="insert_table">Táblázat beszúrása</string>
+ <string name="display_language">Megjelenítési nyelv</string>
+ <string name="alert_cancel">Mégse</string>
+ <string name="tabhost_character">Karakter</string>
+ <string name="calc_alert_double_click_optimal_length">Koppintson duplán a fejlécre optimális szélesség/magasság beállításához.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-hy/strings.xml b/android/source/res/values-hy/strings.xml
new file mode 100644
index 000000000000..6f3353e485e6
--- /dev/null
+++ b/android/source/res/values-hy/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name_settings">LibreOffice Դիտակի կարգավորումներ</string>
+ <string name="app_description">LibreOffice Viewer-ը LibreOffice-ի վրա հիմնված փաստաթղթերի դիտարկիչ է:</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Այս թողարկումը տրամադրվել է $VENDOR -ի կողմից:</string>
+ <string name="about_license">Ցույց տուր արտոնագիրը</string>
+ <string name="about_notice">Ցույց տալ ծանուցումը</string>
+ <string name="create_file">Ստեղծեք նոր նիշք</string>
+ <string name="new_textdocument">Նոր տեքստային փաստաթուղթ</string>
+ <string name="new_presentation">Նոր շնորհանդես</string>
+ <string name="new_spreadsheet">Նոր էլ․ աղյուսակ</string>
+ <string name="new_drawing">Նոր նկարչություն</string>
+ <string name="select_file_to_open">Բացելու համար ընտրեք նիշքը</string>
+ <string name="search_find_previous">Գտեք նախորդը</string>
+ <string name="file_icon_desc">նիշքի պատկերակ</string>
+ <string name="title_recents">Վերջին նիշքերը</string>
+ <string name="title_browser">Բոլոր նիշքերը</string>
+ <string name="pref_category_general">Ընդհանուր</string>
+ <string name="pref_experimental_editing">Փորձարարական ռեժիմ</string>
+ <string name="pref_developer_mode">Մշակողի ռեժիմ</string>
+ <string name="action_about">Մասին</string>
+ <string name="action_parts">Մասեր</string>
+ <string name="action_settings">Կարգավորումներ</string>
+ <string name="action_keyboard">Ցույց տալ ստեղնաշարը</string>
+ <string name="action_save">Պահել</string>
+ <string name="action_save_as">Պահել որպես…</string>
+ <string name="action_fromat">Միացնել ձևաչափը</string>
+ <string name="action_search">Փնտրում</string>
+ <string name="action_UNO_commands">Ուղարկել UNO Cmd</string>
+ <string name="message_saved">Պահպանումն ավարտված է</string>
+ <string name="password">Գաղտնաբառ</string>
+ <string name="action_undo">Հետարկել</string>
+ <string name="action_redo">Կրկին անել</string>
+ <string name="save_alert_dialog_title">Պահե՞լ փաստաթուղթը փակելուց առաջ:</string>
+ <string name="save_document">ՊԱՀԵԼ</string>
+ <string name="action_cancel">Չեղարկել</string>
+ <string name="no_save_document">ՈՉ</string>
+ <string name="action_presentation">Սահիկացուցադրություն</string>
+ <string name="action_add_slide">Ավելացնել սահիկ</string>
+ <string name="slideshow_action_back">Հետ</string>
+ <string name="calc_insert_before">Զետեղել</string>
+ <string name="calc_delete">Ջնջել</string>
+ <string name="calc_hide">Թաքցնել</string>
+ <string name="calc_show">Ցուցադրել</string>
+ <string name="calc_optimal_length">Օպտիմալ երկարություն</string>
+ <string name="calc_adjust_length">Կարգավորել երկարությունը</string>
+ <string name="calc_adjust_height">Կարգավորել Բարձրությունը</string>
+ <string name="calc_adjust_width">Կարգավորել Լայնությունը</string>
+ <string name="calc_optimal_height">Օպտիմալ բարձրություն</string>
+ <string name="calc_optimal_width">Օպտիմալ լայնություն</string>
+ <string name="calc_optimal_length_confirm">ԼԱՎ</string>
+ <string name="action_add_worksheet">Ավելացնել աշխատաթերթիկ</string>
+ <string name="action_pwd_dialog_OK">ԼԱՎ</string>
+ <string name="action_pwd_dialog_cancel">Չեղարկել</string>
+ <string name="action_pwd_dialog_title">Խնդրում ենք մուտքագրել գաղտնաբառը</string>
+ <string name="take_photo">Լուսանկարել</string>
+ <string name="select_photo">Ընտրեք Լուսանկար</string>
+ <string name="select_photo_title">Ընտրեք նկարը</string>
+ <string name="no_camera_found">Տեսախցիկ չի գտնվել</string>
+ <string name="compress_photo_smallest_size">Ամենափոքր Չափը</string>
+ <string name="compress_photo_medium_size">Միջին չափ</string>
+ <string name="compress_photo_no_compress">Մի սեղմեք</string>
+ <string name="compress_photo_title">Ցանկանու՞մ եք սեղմել լուսանկարը:</string>
+ <string name="action_copy">Պատճեն</string>
+ <string name="action_paste">Հետ տեղադրել</string>
+ <string name="action_cut">Կտրել</string>
+ <string name="action_back">Հետ</string>
+ <string name="insert_table">Տեղադրեք աղյուսակ</string>
+ <string name="select_insert_options">Ընտրեք տեղադրման ընտրանքները.</string>
+ <string name="action_rename_worksheet">Անվանափոխեք աշխատաթերթիկը</string>
+ <string name="action_delete_worksheet">Ջնջեք աշխատաթերթիկը</string>
+ <string name="action_delete_slide">Ջնջեք սահիկը</string>
+ <string name="name_already_used">Նշված անունն արդեն օգտագործվում է։</string>
+ <string name="part_deleted">Մասի ջնջված է։</string>
+ <string name="UNO_commands_string_type_hint">Տեսակ</string>
+ <string name="UNO_commands_string_value_hint">Արժեք</string>
+ <string name="UNO_commands_string_parent_value_hint">Ծնողական արժեքը</string>
+ <string name="action_exportToPDF">Արտահանել PDF</string>
+ <string name="action_print">Տպել</string>
+ <string name="tabhost_character">Նիշ</string>
+ <string name="tabhost_paragraph">Պարբերություն</string>
+ <string name="tabhost_insert">Զետեղել</string>
+ <string name="tabhost_style">Ոճ</string>
+ <string name="alert_ok">ԼԱՎ</string>
+ <string name="alert_cancel">Չեղարկել</string>
+ <string name="current_uno_command">Ընթացիկ UNO հրամանը</string>
+ <string name="display_language">Արտածիր լեզուն</string>
+ <string name="display_language_summary">Սահմանեք ցուցադրման լռելյայն լեզուն</string>
+ <string name="pdf_export_finished">PDF արտահանումն ավարտված է</string>
+ <string name="unable_to_export_pdf">Հնարավոր չէ արտահանել pdf</string>
+ <string name="unable_to_save">Հնարավոր չէ պահպանել նիշքը</string>
+ <string name="error">Սխալ</string>
+ <string name="bmp_null">Bmp is null!</string>
+ <string name="page">Էջ</string>
+ <string name="sheet">Թերթ</string>
+ <string name="slide">Սահիկ</string>
+ <string name="part">Մաս</string>
+ <string name="highlight_color">Ընդգծման գույն</string>
+ <string name="font_color">Տառատեսակի գույն</string>
+ <string name="automatic">Ինքնաշխատ</string>
+ <string name="readonly_file">Այս նիշքը միայն-կարդալու է։</string>
+ <string name="part_name_changed">Մասի անվանումը փոխված է։</string>
+ <string name="app_name">LibreOffice Դիտակ</string>
+ <string name="app_version">Version: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_privacy_policy">Գաղտնիության քաղաքականություն</string>
+ <string name="default_document_name">անվերնագիր</string>
+ <string name="pref_experimental_editing_summary">Միացնել փորձարարական խմբագրման ռեժիմը: Օգտագործեք ձեր սեփական ռիսկով:</string>
+ <string name="search_find_next">Գտեք հաջորդը</string>
+ <string name="message_saving">Փաստաթուղթը պահվում է…</string>
+ <string name="pref_developer_mode_summary">Միացրեք մշակողի ռեժիմը, որտեղ կարող եք UNO հրամաններ ուղարկել հավելվածի ներսում: Օգտագործեք ձեր սեփական ռիսկով:</string>
+ <string name="message_saving_failed">Փաստաթղթի պահպանումը ձախողվեց:</string>
+ <string name="calc_alert_double_click_optimal_length">Հուշում. Կրկնակի հպեք վերնագրի վրա՝ սահմանում է օպտիմալ լայնությունը/բարձրությունը:</string>
+ <string name="calc_optimal_length_default_text">Մուտքագրեք լրացուցիչ երկարությունը 100-րդ/մմ</string>
+ <string name="compress_photo_max_quality">Առավելագույն որակ</string>
+ <string name="action_text_copied">Տեքստը պատճենվեց սեղմատախտակին</string>
+ <string name="select_delete_options">Ընտրեք ջնջելու ընտրանքները.</string>
+ <string name="UNO_commands_string_hint">UNO հրաման</string>
+ <string name="enter_part_name">Մուտքագրեք մասի անունը</string>
+ <string name="action_rename_slide">Անվանափոխեք սահիկը</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-ia/strings.xml b/android/source/res/values-ia/strings.xml
new file mode 100644
index 000000000000..09a33ba1608f
--- /dev/null
+++ b/android/source/res/values-ia/strings.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="pref_developer_mode_summary">Activar le modo disveloppator ubi tu pote inviar commandos UNO intra le application. Usa lo sub tu proprie risco.</string>
+ <string name="app_description">LibreOffice Viewer es un visualisator de documentos basate sur LibreOffice.</string>
+ <string name="calc_show">Monstrar</string>
+ <string name="pref_developer_mode">Modo de disveloppator</string>
+ <string name="action_pwd_dialog_cancel">Cancellar</string>
+ <string name="create_file">Crear un nove file</string>
+ <string name="calc_hide">Celar</string>
+ <string name="action_UNO_commands">Inviar commando UNO</string>
+ <string name="default_document_name">sin titulo</string>
+ <string name="action_about">A proposito de</string>
+ <string name="action_fromat">Activar formato</string>
+ <string name="password">Contrasigno</string>
+ <string name="UNO_commands_string_type_hint">Typo</string>
+ <string name="slideshow_action_back">Retro</string>
+ <string name="bmp_null">Bmp non valide!</string>
+ <string name="action_paste">Collar</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="save_document">SALVEGUARDAR</string>
+ <string name="new_spreadsheet">Nove folio de calculo</string>
+ <string name="select_file_to_open">Selige un file a aperir</string>
+ <string name="unable_to_export_pdf">Non poteva exportar a PDF</string>
+ <string name="action_save_as">Salveguardar como…</string>
+ <string name="font_color">Color de littera</string>
+ <string name="new_drawing">Nove designo</string>
+ <string name="automatic">Automatic</string>
+ <string name="action_redo">Refacer</string>
+ <string name="file_icon_desc">icone de file</string>
+ <string name="title_recents">Files recente</string>
+ <string name="page">Pagina</string>
+ <string name="calc_insert_before">Inserer</string>
+ <string name="tabhost_style">Stylo</string>
+ <string name="select_photo_title">Seliger un imagine</string>
+ <string name="no_save_document">NON</string>
+ <string name="new_textdocument">Nove documento de texto</string>
+ <string name="action_print">Imprimer</string>
+ <string name="new_presentation">Nove presentation</string>
+ <string name="pref_experimental_editing">Modo experimental</string>
+ <string name="calc_delete">Deler</string>
+ <string name="action_undo">Disfacer</string>
+ <string name="app_vendor">Iste version es fornite per $VENDOR.</string>
+ <string name="action_pwd_dialog_title">Insere le contrasigno</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="action_parts">Partes</string>
+ <string name="display_language_summary">Definir le lingua predefinite del interfacie</string>
+ <string name="pref_category_general">General</string>
+ <string name="action_text_copied">Texto copiate al area de transferentia</string>
+ <string name="action_exportToPDF">Exportar a PDF</string>
+ <string name="action_keyboard">Monstrar le claviero</string>
+ <string name="about_privacy_policy">Politica de confidentialitate</string>
+ <string name="action_presentation">Presentation de diapositivas</string>
+ <string name="select_photo">Seliger un photo</string>
+ <string name="action_copy">Copiar</string>
+ <string name="tabhost_insert">Inserer</string>
+ <string name="action_search">Cerca</string>
+ <string name="no_camera_found">Necun camera trovate</string>
+ <string name="error">Error</string>
+ <string name="app_name_settings">Parametros del visualisator de LibreOffice</string>
+ <string name="name_already_used">Le nomine fornite jam es in uso.</string>
+ <string name="action_save">Salveguardar</string>
+ <string name="alert_ok">OK</string>
+ <string name="action_settings">Parametros</string>
+ <string name="app_version">Version: %1$s&lt;br&gt;ID de compilation: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_license">Monstrar le licentia</string>
+ <string name="title_browser">Tote le files</string>
+ <string name="unable_to_save">Non poteva salveguardar le file</string>
+ <string name="app_name">Visualisator de LibreOffice</string>
+ <string name="action_add_slide">Adder un diapositiva</string>
+ <string name="action_cancel">Cancellar</string>
+ <string name="display_language">Lingua a monstrar</string>
+ <string name="search_find_next">Trovar le sequente</string>
+ <string name="search_find_previous">Trovar le previe</string>
+ <string name="pref_experimental_editing_summary">Activar le modo de modification experimental. Usa lo sub tu proprie risco.</string>
+ <string name="readonly_file">Iste file es solo lectura</string>
+ <string name="about_notice">Monstrar le aviso</string>
+ <string name="alert_cancel">Cancellar</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-in/strings.xml b/android/source/res/values-in/strings.xml
new file mode 100644
index 000000000000..682f618e1dbe
--- /dev/null
+++ b/android/source/res/values-in/strings.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Penampil LibreOffice</string>
+ <string name="app_name_settings">Pengaturan Penampil LibreOffice</string>
+ <string name="app_version">Versi: %1$s&lt;br&gt;ID Build: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">Penampil LibreOffice adalah suatu penampil dokumen yang berbasis LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Rilis ini disediakan oleh $VENDOR.</string>
+ <string name="readonly_file">Berkas ini hanya-baca.</string>
+ <string name="about_license">Tampilkan Lisensi</string>
+ <string name="about_notice">Tampilkan Pemberitahuan</string>
+ <string name="about_privacy_policy">Kebijakan Privasi</string>
+ <string name="create_file">Buat Berkas Baru</string>
+ <string name="new_textdocument">Dokumen Teks Baru</string>
+ <string name="new_presentation">Presentasi Baru</string>
+ <string name="new_spreadsheet">Lembar Kerja Baru</string>
+ <string name="new_drawing">Gambar Baru</string>
+ <string name="default_document_name">tanpa judul</string>
+ <string name="select_file_to_open">Pilih berkas yang akan dibuka</string>
+ <string name="search_find_next">Cari Selanjutnya</string>
+ <string name="file_icon_desc">fileicon</string>
+ <string name="title_recents">Berkas baru-baru Ini</string>
+ <string name="title_browser">Semua berkas</string>
+ <string name="pref_category_general">Umum</string>
+ <string name="pref_experimental_editing">Mode Eksperimen</string>
+ <string name="pref_developer_mode">Mode Pengembang</string>
+ <string name="pref_developer_mode_summary">Memfungsikan mode pengembang dimana Anda dapat mengirim perintah-perintah UNO di dalam app. Risiko Anda tanggung sendiri.</string>
+ <string name="action_about">Tentang</string>
+ <string name="action_settings">Pengaturan</string>
+ <string name="action_keyboard">Tampilkan papan ketik</string>
+ <string name="action_save">Simpan</string>
+ <string name="action_fromat">Fungsikan Format</string>
+ <string name="action_search">Cari</string>
+ <string name="action_UNO_commands">Kirim Perintah UNO</string>
+ <string name="message_saved">Penyimpanan selesai</string>
+ <string name="message_saving">Menyimpan dokumen…</string>
+ <string name="message_saving_failed">Penyimpanan dokumen gagal.</string>
+ <string name="password">Kata Sandi</string>
+ <string name="action_undo">Tak Jadi</string>
+ <string name="action_redo">Jadi Lagi</string>
+ <string name="action_parts">Bagian</string>
+ <string name="action_cancel">Batal</string>
+ <string name="no_save_document">TIDAK</string>
+ <string name="action_add_slide">Tambah Salindia</string>
+ <string name="action_cut">Potong</string>
+ <string name="insert_table">Sisip tabel</string>
+ <string name="select_insert_options">Pilih opsi sisip:</string>
+ <string name="select_delete_options">Pilih opsi hapus:</string>
+ <string name="action_rename_worksheet">Ubah nama lembar kerja</string>
+ <string name="action_delete_worksheet">Hapus lembar kerja</string>
+ <string name="action_delete_slide">Hapus salindia</string>
+ <string name="name_already_used">Nama yang diberikan sudah terpakai.</string>
+ <string name="part_name_changed">Nama bagian telah diubah.</string>
+ <string name="UNO_commands_string_hint">Perintah UNO</string>
+ <string name="UNO_commands_string_type_hint">Tipe</string>
+ <string name="UNO_commands_string_value_hint">Nilai</string>
+ <string name="UNO_commands_string_parent_value_hint">Nilai Induk</string>
+ <string name="action_exportToPDF">Ekspor Ke PDF</string>
+ <string name="action_print">Cetak</string>
+ <string name="tabhost_character">Karakter</string>
+ <string name="tabhost_paragraph">Paragraf</string>
+ <string name="tabhost_insert">Sisip</string>
+ <string name="tabhost_style">Gaya</string>
+ <string name="alert_ok">OK</string>
+ <string name="alert_cancel">Batal</string>
+ <string name="current_uno_command">Perintah UNO saat ini</string>
+ <string name="display_language">Bahasa Tampilan</string>
+ <string name="display_language_summary">Atur bahasa tampilan baku</string>
+ <string name="pdf_export_finished">Ekspor PDF telah selesai</string>
+ <string name="unable_to_export_pdf">Tidak bisa mengekspor ke pdf</string>
+ <string name="unable_to_save">Tidak bisa menyimpan berkas</string>
+ <string name="error">Galat</string>
+ <string name="enter_part_name">Masukkan suatu nama bagian</string>
+ <string name="bmp_null">Bmp adalah null!</string>
+ <string name="page">Halaman</string>
+ <string name="sheet">Lembar</string>
+ <string name="slide">Salindia</string>
+ <string name="part">Bagian</string>
+ <string name="highlight_color">Warna Penyorotan</string>
+ <string name="font_color">Warna Fonta</string>
+ <string name="action_rename_slide">Ubah Nama Salindia</string>
+ <string name="automatic">Otomatis</string>
+ <string name="search_find_previous">Cari Sebelumnya</string>
+ <string name="save_document">SIMPAN</string>
+ <string name="pref_experimental_editing_summary">Memfungsikan mode penyuntingan eksperimen. Risiko Anda tanggung sendiri.</string>
+ <string name="save_alert_dialog_title">Simpan dokumen sebelum menutup?</string>
+ <string name="action_presentation">Pertunjukan salindia</string>
+ <string name="action_back">Mundur</string>
+ <string name="action_text_copied">Teks disalin ke papan klip</string>
+ <string name="part_deleted">Bagian telah dihapus.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-is/strings.xml b/android/source/res/values-is/strings.xml
new file mode 100644
index 000000000000..ba8d367ce4a9
--- /dev/null
+++ b/android/source/res/values-is/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">LibreOffice-skoðari</string>
+ <string name="app_name_settings">Stillingar LibreOffice-skoðara</string>
+ <string name="app_version">Útgáfa: %1$s&lt;br&gt;Byggingarauðkenni: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_privacy_policy">Meðferð persónuupplýsinga</string>
+ <string name="create_file">Búa til nýja skrá</string>
+ <string name="search_find_next">Finna næsta</string>
+ <string name="search_find_previous">Finna fyrra</string>
+ <string name="action_save_as">Vista sem…</string>
+ <string name="page">Síða</string>
+ <string name="sheet">Blað</string>
+ <string name="slide">Skyggna</string>
+ <string name="part">Hluti</string>
+ <string name="highlight_color">Áherslulitur</string>
+ <string name="font_color">Litur á letri</string>
+ <string name="action_rename_slide">Endurnefna skyggnu</string>
+ <string name="automatic">Sjálfvirkt</string>
+ <string name="app_description">LibreOffice-skoðarinn er skjalaskoðari byggður á LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">"Þessi útgáfa var gefin út af $VENDOR."</string>
+ <string name="readonly_file">Þessi skrá er aðeins lesanleg.</string>
+ <string name="about_license">Birta notkunarleyfi</string>
+ <string name="about_notice">Birta tilkynningu</string>
+ <string name="new_textdocument">Nýtt textaskjal</string>
+ <string name="new_presentation">Ný kynning</string>
+ <string name="new_spreadsheet">Nýr töflureiknir</string>
+ <string name="new_drawing">Ný teikning</string>
+ <string name="default_document_name">ónefnt</string>
+ <string name="select_file_to_open">Veldu skrá til að opna</string>
+ <string name="title_recents">Nýlegar skrár</string>
+ <string name="title_browser">Allar skrár</string>
+ <string name="pref_category_general">Almennt</string>
+ <string name="pref_experimental_editing">Tilraunahamur</string>
+ <string name="pref_experimental_editing_summary">Virkjaðu ham á tilraunastigi. Notist á eigin ábyrgð.</string>
+ <string name="pref_developer_mode">Forritarahamur</string>
+ <string name="pref_developer_mode_summary">Virkjaðu forritaraham þar sem þú getur sent UNO-skipanir innan forritsins. Notist á eigin ábyrgð.</string>
+ <string name="action_about">Um hugbúnaðinn</string>
+ <string name="action_parts">Hlutar</string>
+ <string name="action_settings">Stillingar</string>
+ <string name="action_keyboard">Birta lyklaborð</string>
+ <string name="action_save">Vista</string>
+ <string name="action_fromat">Virkja snið</string>
+ <string name="action_search">Leita</string>
+ <string name="action_UNO_commands">Senda UNO-skipun</string>
+ <string name="message_saved">Vistun lokið</string>
+ <string name="message_saving">Vista skjalið…</string>
+ <string name="message_saving_failed">Vistun skjalsins mistókst.</string>
+ <string name="password">Lykilorð</string>
+ <string name="action_undo">Afturkalla</string>
+ <string name="action_redo">Endurgera</string>
+ <string name="save_alert_dialog_title">Vista skjalið áður en því er lokað\?</string>
+ <string name="save_document">VISTA</string>
+ <string name="action_cancel">Hætta við</string>
+ <string name="no_save_document">NEI</string>
+ <string name="action_presentation">Skyggnusýning</string>
+ <string name="action_add_slide">Bæta við skyggnu</string>
+ <string name="slideshow_action_back">Til baka</string>
+ <string name="calc_insert_before">Setja inn</string>
+ <string name="calc_delete">Eyða</string>
+ <string name="calc_hide">Fela</string>
+ <string name="calc_show">Birta</string>
+ <string name="calc_optimal_length">Besta lengd</string>
+ <string name="calc_adjust_length">Aðlaga lengd</string>
+ <string name="calc_adjust_height">Aðlaga hæð</string>
+ <string name="calc_adjust_width">Aðlaga breidd</string>
+ <string name="calc_optimal_height">Besta hæð</string>
+ <string name="calc_optimal_width">Besta breidd</string>
+ <string name="calc_optimal_length_confirm">Í lagi</string>
+ <string name="calc_optimal_length_default_text">Settu inn viðbótarlengd í hundruðustu hlutum mm</string>
+ <string name="calc_alert_double_click_optimal_length">Ábending: Tvíbank á fyrirsögn setur bestu breidd/hæð.</string>
+ <string name="action_add_worksheet">Bæta við töflureikniblaði</string>
+ <string name="action_pwd_dialog_OK">Í lagi</string>
+ <string name="action_pwd_dialog_cancel">Hætta við</string>
+ <string name="action_pwd_dialog_title">Settu inn lykilorð</string>
+ <string name="take_photo">Taka ljósmynd</string>
+ <string name="select_photo">Veldu ljósmynd</string>
+ <string name="select_photo_title">Veldu mynd</string>
+ <string name="no_camera_found">Engin myndavél fannst</string>
+ <string name="compress_photo_smallest_size">Minnsta stærð</string>
+ <string name="compress_photo_medium_size">Miðlungsstærð</string>
+ <string name="compress_photo_max_quality">Hámarksgæði</string>
+ <string name="compress_photo_no_compress">Ekki þjappa</string>
+ <string name="compress_photo_title">Viltu þjappa ljósmyndinni\?</string>
+ <string name="action_copy">Afrita</string>
+ <string name="action_paste">Líma</string>
+ <string name="action_cut">Klippa</string>
+ <string name="action_back">Til baka</string>
+ <string name="action_text_copied">Texti afritaður á klippispjaldið</string>
+ <string name="insert_table">Setja inn töflu</string>
+ <string name="select_insert_options">Veldu valkosti innsetingar:</string>
+ <string name="select_delete_options">Veldu valkosti eyðingar:</string>
+ <string name="action_rename_worksheet">Endurnefna vinnublað</string>
+ <string name="action_delete_worksheet">Eyða vinnublaði</string>
+ <string name="action_delete_slide">Eyða skyggnu</string>
+ <string name="name_already_used">Uppgefið heiti er þegar í notkun.</string>
+ <string name="part_name_changed">Heiti hlutans hefur verið breytt.</string>
+ <string name="part_deleted">Hluta hefur verið eytt.</string>
+ <string name="UNO_commands_string_hint">UNO-skipun</string>
+ <string name="UNO_commands_string_type_hint">Tegund</string>
+ <string name="UNO_commands_string_value_hint">Gildi</string>
+ <string name="UNO_commands_string_parent_value_hint">Yfirgildi</string>
+ <string name="action_exportToPDF">Flytja út í PDF</string>
+ <string name="action_print">Prenta</string>
+ <string name="tabhost_character">Stafur</string>
+ <string name="tabhost_paragraph">Málsgrein</string>
+ <string name="tabhost_insert">Setja inn</string>
+ <string name="tabhost_style">Stíll</string>
+ <string name="alert_ok">Í lagi</string>
+ <string name="alert_cancel">Hætta við</string>
+ <string name="current_uno_command">Fyrirliggjandi UNO-skipun</string>
+ <string name="display_language">Birt tungumál</string>
+ <string name="display_language_summary">Settu sjálfgefið birtingartungumál</string>
+ <string name="pdf_export_finished">Útflutningi í PDF er lokið</string>
+ <string name="unable_to_export_pdf">Tókst ekki að flytja út í PDF</string>
+ <string name="unable_to_save">Get ekki vistað skrá</string>
+ <string name="error">Villa</string>
+ <string name="enter_part_name">Settu inn heiti á hluta</string>
+ <string name="bmp_null">Bmp er núll!</string>
+ <string name="file_icon_desc">skráartákn</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-it/strings.xml b/android/source/res/values-it/strings.xml
new file mode 100644
index 000000000000..35dade166124
--- /dev/null
+++ b/android/source/res/values-it/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name_settings">Impostazioni del Visualizzatore di LibreOffice</string>
+ <string name="app_credits">https://it.libreoffice.org/</string>
+ <string name="app_vendor">Versione fornita da $VENDOR.</string>
+ <string name="readonly_file">Questo file è di sola lettura.</string>
+ <string name="about_license">Mostra licenza</string>
+ <string name="app_name">Visualizzatore di LibreOffice</string>
+ <string name="app_description">Il Visualizzatore di LibreOffice è un\'app per visualizzare i documenti basata su LibreOffice.</string>
+ <string name="about_notice">Mostra avviso</string>
+ <string name="new_textdocument">Nuovo documento di testo</string>
+ <string name="new_presentation">Nuova presentazione</string>
+ <string name="new_spreadsheet">Nuovo foglio di calcolo</string>
+ <string name="new_drawing">Nuovo disegno</string>
+ <string name="default_document_name">senza titolo</string>
+ <string name="select_file_to_open">Seleziona file da aprire</string>
+ <string name="app_version">Versione: %1$s&lt;br&gt;ID Build: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="title_recents">File recenti</string>
+ <string name="title_browser">Tutti i file</string>
+ <string name="pref_category_general">Generale</string>
+ <string name="pref_experimental_editing">Modalità sperimentale</string>
+ <string name="pref_experimental_editing_summary">Attiva la modalità di modifica sperimentale a tuo rischio e sotto la tua responsabilità.</string>
+ <string name="pref_developer_mode">Modalità sviluppatore</string>
+ <string name="pref_developer_mode_summary">Attiva la modalità sviluppatore per inviare comandi UNO direttamente dall\'app. Il suo uso è a tuo rischio e sotto la tua responsabilità.</string>
+ <string name="action_about">Informazioni</string>
+ <string name="action_parts">Parti</string>
+ <string name="action_settings">Impostazioni</string>
+ <string name="action_keyboard">Mostra tastiera</string>
+ <string name="action_search">Cerca</string>
+ <string name="action_UNO_commands">Invia comando UNO</string>
+ <string name="message_saved">Salvataggio completato</string>
+ <string name="message_saving">Salvataggio del documento…</string>
+ <string name="message_saving_failed">Impossibile salvare il documento.</string>
+ <string name="password">Password</string>
+ <string name="action_undo">Annulla</string>
+ <string name="action_redo">Ripeti</string>
+ <string name="save_document">SALVA</string>
+ <string name="action_cancel">Annulla</string>
+ <string name="no_save_document">NO</string>
+ <string name="action_presentation">Presentazione</string>
+ <string name="action_add_slide">Aggiungi diapositiva</string>
+ <string name="action_save">Salva</string>
+ <string name="action_fromat">Attiva formato</string>
+ <string name="save_alert_dialog_title">Salvare il documento prima di chiuderlo\?</string>
+ <string name="pdf_export_finished">Esportazione in PDF terminata</string>
+ <string name="calc_show">Mostra</string>
+ <string name="action_pwd_dialog_cancel">Annulla</string>
+ <string name="create_file">Crea nuovo file</string>
+ <string name="slide">Diapositiva</string>
+ <string name="part_name_changed">Il nome della parte è stato modificato.</string>
+ <string name="compress_photo_max_quality">Massima qualità</string>
+ <string name="calc_hide">Nascondi</string>
+ <string name="select_insert_options">Scegli opzioni di inserimento:</string>
+ <string name="UNO_commands_string_type_hint">Tipo</string>
+ <string name="current_uno_command">Comando UNO attuale</string>
+ <string name="slideshow_action_back">Indietro</string>
+ <string name="bmp_null">File Bitmap non valido.</string>
+ <string name="action_paste">Incolla</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="calc_adjust_length">Regola la lunghezza</string>
+ <string name="part">Parte</string>
+ <string name="unable_to_export_pdf">Impossibile esportare in PDF</string>
+ <string name="action_save_as">Salva con nome…</string>
+ <string name="font_color">Colore carattere</string>
+ <string name="action_rename_worksheet">Rinomina foglio di lavoro</string>
+ <string name="calc_optimal_length">Lunghezza ottimale</string>
+ <string name="enter_part_name">Inserisci un nome per la parte</string>
+ <string name="automatic">Automatico</string>
+ <string name="action_delete_slide">Elimina diapositiva</string>
+ <string name="action_cut">Taglia</string>
+ <string name="file_icon_desc">iconafile</string>
+ <string name="page">Pagina</string>
+ <string name="calc_insert_before">Inserisci</string>
+ <string name="calc_optimal_length_default_text">Inserisci lunghezza aggiuntiva in centesimi di millimetro</string>
+ <string name="tabhost_style">Stile</string>
+ <string name="select_photo_title">Seleziona immagine</string>
+ <string name="calc_optimal_width">Larghezza ottimale</string>
+ <string name="action_delete_worksheet">Elimina foglio di lavoro</string>
+ <string name="highlight_color">Colore evidenziazione</string>
+ <string name="action_print">Stampa</string>
+ <string name="calc_adjust_width">Regola la larghezza</string>
+ <string name="action_add_worksheet">Aggiungi foglio di calcolo</string>
+ <string name="tabhost_paragraph">Paragrafo</string>
+ <string name="action_back">Indietro</string>
+ <string name="calc_delete">Elimina</string>
+ <string name="part_deleted">La parte è stata eliminata.</string>
+ <string name="action_pwd_dialog_title">Inserisci password</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="compress_photo_medium_size">Dimensione media</string>
+ <string name="display_language_summary">Imposta lingua di visualizzazione predefinita</string>
+ <string name="select_delete_options">Scegli opzioni di eliminazione:</string>
+ <string name="action_text_copied">Testo copiato negli appunti</string>
+ <string name="action_exportToPDF">Esporta in PDF</string>
+ <string name="action_rename_slide">Rinomina diapositiva</string>
+ <string name="about_privacy_policy">Informativa sulla riservatezza</string>
+ <string name="UNO_commands_string_parent_value_hint">Valore padre</string>
+ <string name="compress_photo_smallest_size">Dimensione minima</string>
+ <string name="select_photo">Seleziona foto</string>
+ <string name="compress_photo_no_compress">Nessuna compressione</string>
+ <string name="action_copy">Copia</string>
+ <string name="tabhost_insert">Inserisci</string>
+ <string name="no_camera_found">Fotocamera non trovata</string>
+ <string name="error">Errore</string>
+ <string name="name_already_used">Il nome specificato è già in uso.</string>
+ <string name="UNO_commands_string_hint">Comando UNO</string>
+ <string name="alert_ok">OK</string>
+ <string name="UNO_commands_string_value_hint">Valore</string>
+ <string name="sheet">Foglio</string>
+ <string name="compress_photo_title">Comprimere la foto\?</string>
+ <string name="take_photo">Fai una foto</string>
+ <string name="unable_to_save">Impossibile salvare il file</string>
+ <string name="insert_table">Inserisci tabella</string>
+ <string name="calc_adjust_height">Regola l\'altezza</string>
+ <string name="display_language">Mostra lingua</string>
+ <string name="search_find_next">Trova successivo</string>
+ <string name="search_find_previous">Trova precedente</string>
+ <string name="alert_cancel">Annulla</string>
+ <string name="calc_optimal_height">Altezza ottimale</string>
+ <string name="tabhost_character">Carattere</string>
+ <string name="calc_alert_double_click_optimal_length">Suggerimento: doppio tocco su un\'intestazione imposta altezza/larghezza ottimale.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-ja/strings.xml b/android/source/res/values-ja/strings.xml
new file mode 100644
index 000000000000..a6b3daec9354
--- /dev/null
+++ b/android/source/res/values-ja/strings.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources></resources> \ No newline at end of file
diff --git a/android/source/res/values-kk/strings.xml b/android/source/res/values-kk/strings.xml
new file mode 100644
index 000000000000..a6b3daec9354
--- /dev/null
+++ b/android/source/res/values-kk/strings.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources></resources> \ No newline at end of file
diff --git a/android/source/res/values-ne/strings.xml b/android/source/res/values-ne/strings.xml
new file mode 100644
index 000000000000..430de40d93d2
--- /dev/null
+++ b/android/source/res/values-ne/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_version">संस्करण: %1$s&lt;br&gt;बिल्ड आइडी: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">यो संस्करण $VENDOR द्वारा प्रदान गरिएको हो।</string>
+ <string name="readonly_file">यो फाइल हेर्न-मात्र-मिल्ने छ।</string>
+ <string name="about_notice">सूचना देखाउनुहोस्</string>
+ <string name="new_textdocument">नयाँ पाठ कागजात</string>
+ <string name="new_presentation">नयाँ प्रस्तुति</string>
+ <string name="new_spreadsheet">नयाँ स्प्रेडसिट</string>
+ <string name="new_drawing">नयाँ ड्रइङ</string>
+ <string name="select_file_to_open">खोल्नको लागि फाइल रोज्नुहोस्</string>
+ <string name="file_icon_desc">फाइलआइकन</string>
+ <string name="title_recents">हालका फाइलहरू</string>
+ <string name="pref_category_general">सामान्य</string>
+ <string name="pref_experimental_editing">प्रयोगात्मक मोड</string>
+ <string name="app_name">लिब्रेअफिस भ्युअर</string>
+ <string name="app_name_settings">लिब्रेअफिस भ्युअर सेटिङ</string>
+ <string name="app_description">लिब्रेअफिस भ्युअर लिब्रेअफिसमा आधारित कागजात भ्युअर हो।</string>
+ <string name="default_document_name">शीर्षक नभएको</string>
+ <string name="about_license">इजाजतपत्र देखाउनुहोस्</string>
+ <string name="title_browser">सबै फाइलहरू</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-night/colors.xml b/android/source/res/values-night/colors.xml
new file mode 100644
index 000000000000..c6260c191d3e
--- /dev/null
+++ b/android/source/res/values-night/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="background_floating">@color/background_floating_material_dark</color>
+
+ <color name="toolbar_foreground">#efefef</color>
+</resources>
diff --git a/android/source/res/values-nl/strings.xml b/android/source/res/values-nl/strings.xml
new file mode 100644
index 000000000000..1e8879288993
--- /dev/null
+++ b/android/source/res/values-nl/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name_settings">LibreOffice Viewer-instellingen</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Deze uitgave is geleverd door $VENDOR.</string>
+ <string name="readonly_file">Dit bestand is alleen-lezen.</string>
+ <string name="about_license">Licentie inzien</string>
+ <string name="about_notice">Notitie weergeven</string>
+ <string name="about_privacy_policy">Privacybeleid</string>
+ <string name="create_file">Nieuw bestand maken</string>
+ <string name="new_presentation">Nieuwe presentatie</string>
+ <string name="new_spreadsheet">Nieuw werkblad</string>
+ <string name="new_drawing">Nieuwe tekening</string>
+ <string name="default_document_name">naamloos</string>
+ <string name="select_file_to_open">Selecteer te openen bestand</string>
+ <string name="search_find_next">Volgende zoeken</string>
+ <string name="search_find_previous">Vorige zoeken</string>
+ <string name="file_icon_desc">Bestandspictogram</string>
+ <string name="title_recents">Recent geopende bestanden</string>
+ <string name="title_browser">Alle bestanden</string>
+ <string name="pref_category_general">Algemeen</string>
+ <string name="pref_experimental_editing_summary">Schakel de experimentele bewerkingsmodus in. Gebruik op eigen risico.</string>
+ <string name="pref_developer_mode">Ontwikkelaarsmodus</string>
+ <string name="action_about">Info</string>
+ <string name="action_parts">Gedeeltes</string>
+ <string name="action_settings">Instellingen</string>
+ <string name="action_keyboard">Toetsenbord weergeven</string>
+ <string name="action_save">Opslaan</string>
+ <string name="action_search">Zoeken</string>
+ <string name="action_fromat">Indeling inschakelen</string>
+ <string name="message_saving">Het document wordt opgeslagen…</string>
+ <string name="message_saving_failed">Opslaan van het document is mislukt.</string>
+ <string name="password">Wachtwoord</string>
+ <string name="action_undo">Ongedaan maken</string>
+ <string name="action_redo">Opnieuw</string>
+ <string name="save_document">OPSLAAN</string>
+ <string name="action_cancel">Annuleren</string>
+ <string name="no_save_document">Nee</string>
+ <string name="action_presentation">Presentatie</string>
+ <string name="action_add_slide">Dia toevoegen</string>
+ <string name="slideshow_action_back">Terug</string>
+ <string name="calc_insert_before">Invoegen</string>
+ <string name="calc_delete">Verwijderen</string>
+ <string name="calc_hide">Verbergen</string>
+ <string name="calc_show">Weergeven</string>
+ <string name="calc_optimal_length">Optimale lengte</string>
+ <string name="calc_adjust_length">Lengte aanpassen</string>
+ <string name="calc_adjust_height">Hoogte aanpassen</string>
+ <string name="calc_adjust_width">Breedte aanpassen</string>
+ <string name="calc_optimal_height">Optimale hoogte</string>
+ <string name="calc_optimal_width">Optimale breedte</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="calc_alert_double_click_optimal_length">Tip: Dubbeltik op een koptekst om de optimale breedte/hoogte in te stellen.</string>
+ <string name="action_add_worksheet">Werkblad toevoegen</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="action_pwd_dialog_cancel">Annuleren</string>
+ <string name="action_pwd_dialog_title">Wachtwoord invoeren alstublieft</string>
+ <string name="take_photo">Foto maken</string>
+ <string name="select_photo">Foto selecteren</string>
+ <string name="select_photo_title">Afbeelding selecteren</string>
+ <string name="no_camera_found">Geen camera gevonden</string>
+ <string name="compress_photo_smallest_size">Kleinste maat</string>
+ <string name="compress_photo_medium_size">Middelgroot</string>
+ <string name="compress_photo_no_compress">Niet comprimeren</string>
+ <string name="compress_photo_title">Wilt u de foto comprimeren\?</string>
+ <string name="action_paste">Plakken</string>
+ <string name="action_cut">Knippen</string>
+ <string name="insert_table">Tabel invoegen</string>
+ <string name="select_insert_options">Invoegopties selecteren:</string>
+ <string name="select_delete_options">Verwijderopties selecteren:</string>
+ <string name="action_rename_worksheet">Werkblad hernoemen</string>
+ <string name="action_delete_worksheet">Werkblad verwijderen</string>
+ <string name="action_delete_slide">Dia verwijderen</string>
+ <string name="name_already_used">De opgegeven naam wordt al gebruikt.</string>
+ <string name="part_deleted">De sectie is verwijderd.</string>
+ <string name="UNO_commands_string_hint">UNO-opdracht</string>
+ <string name="UNO_commands_string_type_hint">Type</string>
+ <string name="UNO_commands_string_value_hint">Waarde</string>
+ <string name="UNO_commands_string_parent_value_hint">Bovenliggende waarde</string>
+ <string name="action_exportToPDF">Als PDF exporteren</string>
+ <string name="action_print">Afdrukken</string>
+ <string name="tabhost_character">Teken</string>
+ <string name="tabhost_paragraph">Alinea</string>
+ <string name="tabhost_insert">Invoegen</string>
+ <string name="tabhost_style">Opmaakprofiel</string>
+ <string name="alert_ok">OK</string>
+ <string name="alert_cancel">Annuleren</string>
+ <string name="current_uno_command">Huidige UNO-opdracht</string>
+ <string name="display_language">Taal weergeven</string>
+ <string name="pdf_export_finished">PDF-export voltooit</string>
+ <string name="unable_to_export_pdf">Kan niet exporteren naar PDF</string>
+ <string name="unable_to_save">Kan bestand niet opslaan</string>
+ <string name="error">Fout</string>
+ <string name="enter_part_name">Voer de sectienaam in</string>
+ <string name="bmp_null">Bmp is null!</string>
+ <string name="sheet">Blad</string>
+ <string name="slide">Dia</string>
+ <string name="part">Sectie</string>
+ <string name="highlight_color">Kleur benadrukken</string>
+ <string name="action_rename_slide">Dia hernoemen</string>
+ <string name="automatic">Automatisch</string>
+ <string name="action_UNO_commands">UNO-opdracht sturen</string>
+ <string name="app_version">Versie: %1$s&lt;br&gt;Build ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="new_textdocument">Volgend tekstdocument</string>
+ <string name="app_description">LibreOffice Viewer is een documentviewer gebaseerd op LibreOffice.</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="pref_experimental_editing">Experimentele modus</string>
+ <string name="pref_developer_mode_summary">Schakel de ontwikkelaarsmodus in, waarin u UNO-opdrachten binnen de app kunt verzenden. Gebruik op eigen risico.</string>
+ <string name="action_save_as">Opslaan als…</string>
+ <string name="message_saved">Opslaan voltooit</string>
+ <string name="save_alert_dialog_title">Het document opslaan voordat u het sluit\?</string>
+ <string name="calc_optimal_length_default_text">Extra lengte invoeren in 100ste/mm</string>
+ <string name="compress_photo_max_quality">Maximale kwaliteit</string>
+ <string name="action_copy">Kopiëren</string>
+ <string name="action_back">Terug</string>
+ <string name="action_text_copied">Tekst naar het klembord gekopieerd</string>
+ <string name="part_name_changed">De naam voor de sectie is gewijzigd.</string>
+ <string name="display_language_summary">De standaard weergavetaal instellen</string>
+ <string name="page">Pagina</string>
+ <string name="font_color">Tekstkleur</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-pa/strings.xml b/android/source/res/values-pa/strings.xml
new file mode 100644
index 000000000000..92fd72bdc265
--- /dev/null
+++ b/android/source/res/values-pa/strings.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="action_save_as">…ਵਜੋਂ ਸੰਭਾਲੋ</string>
+ <string name="compress_photo_medium_size">ਮੱਧਮ ਆਕਾਰ</string>
+ <string name="app_description">LibreOffice ਦਰਸ਼ਕ LibreOffice ਉੱਤੇ ਅਧਾਰਿਤ ਦਸਤਾਵੇਜ਼ ਦਰਸ਼ਕ ਹੈ।</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">ਇਹ ਰੀਲਿਜ਼ $VENDOR ਵਲੋਂ ਤਿਆਰ ਕੀਤਾ ਗਿਆ ਸੀ।</string>
+ <string name="readonly_file">ਇਹ ਫਾਈਲ ਸਿਰਫ਼ ਪੜ੍ਹਨ ਲਈ ਹੈ।</string>
+ <string name="about_license">ਲਸੰਸ ਵੇਖਾਓ</string>
+ <string name="about_notice">ਨੋਟਿਸ ਵੇਖਾਓ</string>
+ <string name="create_file">ਨਵੀਂ ਫਾਈਲ ਬਣਾਓ</string>
+ <string name="new_textdocument">ਨਵਾਂ ਟੈਕਸਟ ਦਸਤਾਵੇਜ਼</string>
+ <string name="new_presentation">ਨਵੀਂ ਪੇਸ਼ਕਾਰੀ</string>
+ <string name="new_spreadsheet">ਨਵੀਂ ਸਪਰੈਡਸ਼ੀਟ</string>
+ <string name="new_drawing">ਨਵੀਂ ਡਰਾਇੰਗ</string>
+ <string name="select_file_to_open">ਖੋਲ੍ਹਣ ਲਈ ਫਾਈਲ ਚੁਣੋ</string>
+ <string name="title_recents">ਸੱਜਰੀਆਂ ਫਾਈਲਾਂ</string>
+ <string name="title_browser">ਸਾਰੀਆਂ ਫਾਈਲਾਂ</string>
+ <string name="pref_category_general">ਆਮ</string>
+ <string name="pref_experimental_editing">ਤਜਰਬੇਅਧੀਨ ਢੰਗ</string>
+ <string name="pref_developer_mode">ਡਿਵੈਲਪਰ ਢੰਗ</string>
+ <string name="action_about">ਇਸ ਬਾਰੇ</string>
+ <string name="action_parts">ਹਿੱਸੇ</string>
+ <string name="action_settings">ਸੈਟਿੰਗਾਂ</string>
+ <string name="action_keyboard">ਕੀਬੋਰਡ ਵੇਖਾਓ</string>
+ <string name="action_save">ਸੰਭਾਲੋ</string>
+ <string name="action_fromat">ਫਾਰਮੈਟ ਸਮਰੱਥ ਕਰੋ</string>
+ <string name="action_search">ਖੋਜੋ</string>
+ <string name="message_saved">ਸੰਭਾਲਣਾ ਸੰਭਾਲੋ</string>
+ <string name="message_saving_failed">ਦਸਤਾਵੇਜ਼ ਸੰਭਾਲਣ ਲਈ ਅਸਫ਼ਲ ਹੈ।</string>
+ <string name="password">ਪਾਸਵਰਡ</string>
+ <string name="action_undo">ਵਾਪਸ ਲਵੋ</string>
+ <string name="action_redo">ਫੇਰ ਕਰੋ</string>
+ <string name="save_document">ਸੰਭਾਲੋ</string>
+ <string name="action_cancel">ਰੱਦ ਕਰੋ</string>
+ <string name="no_save_document">ਨਹੀਂ</string>
+ <string name="action_presentation">ਸਲਾਈਡ ਸ਼ੋਅ</string>
+ <string name="slideshow_action_back">ਪਿੱਛੇ</string>
+ <string name="calc_insert_before">ਸ਼ਾਮਲ ਕਰੋ</string>
+ <string name="calc_delete">ਹਟਾਓ</string>
+ <string name="calc_hide">ਓਹਲੇ</string>
+ <string name="calc_show">ਵੇਖਾਓ</string>
+ <string name="calc_adjust_length">ਲੰਬਾਈ ਅਡਜੱਸਟ ਕਰੋ</string>
+ <string name="calc_adjust_height">ਉਚਾਈ ਅਡਜੱਸਟ ਕਰੋ</string>
+ <string name="calc_adjust_width">ਚੌੜਾਈ ਅਡਜੱਸਟ ਕਰੋ</string>
+ <string name="calc_optimal_width">ਚੌੜਾਈ ਅਨੁਕੂਲ ਕਰੋ</string>
+ <string name="calc_optimal_length_confirm">ਠੀਕ ਹੈ</string>
+ <string name="action_add_worksheet">ਵਰਕਸ਼ੀਟ ਜੋੜੋ</string>
+ <string name="action_pwd_dialog_OK">ਠੀਕ ਹੈ</string>
+ <string name="action_pwd_dialog_cancel">ਰੱਦ ਕਰੋ</string>
+ <string name="action_pwd_dialog_title">ਪਾਸਵਰਡ ਦਿਓ</string>
+ <string name="select_photo_title">ਤਸਵੀਰ ਚੁਣੋ</string>
+ <string name="no_camera_found">ਕੋਈ ਕੈਮਰਾ ਨਹੀਂ ਲੱਭਿਆ</string>
+ <string name="compress_photo_smallest_size">ਸਭ ਤੋਂ ਛੋਟਾ ਆਕਾਰ</string>
+ <string name="compress_photo_max_quality">ਵੱਧ ਤੋਂ ਵੱਧ ਕੁਆਲਟੀ</string>
+ <string name="compress_photo_no_compress">ਕੰਪਰੈਸ ਨਾ ਕਰੋ</string>
+ <string name="action_copy">ਕਾਪੀ ਕਰੋ</string>
+ <string name="action_paste">ਚੇਪੋ</string>
+ <string name="action_cut">ਕੱਟੋ</string>
+ <string name="action_back">ਪਿੱਛੇ</string>
+ <string name="insert_table">ਸਾਰਣੀ ਸ਼ਾਮਲ ਕਰੋ</string>
+ <string name="select_insert_options">ਸ਼ਾਮਲ ਕਰਨ ਦੀਆਂ ਚੋਣਾਂ ਚੁਣੋ:</string>
+ <string name="select_delete_options">ਹਟਾਉਣ ਦੀਆਂ ਚੋਣਾਂ ਚੁਣੋ:</string>
+ <string name="action_delete_worksheet">ਵਰਕਸ਼ੀਟ ਹਟਾਓ</string>
+ <string name="action_delete_slide">ਸਲਾਈਡ ਨੂੰ ਹਟਾਓ</string>
+ <string name="action_exportToPDF">PDF ਵਜੋਂ ਐਕਸਪੋਰਟ ਕਰੋ</string>
+ <string name="action_print">ਛਾਪੋ</string>
+ <string name="tabhost_character">ਅੱਖਰ</string>
+ <string name="tabhost_paragraph">ਪ੍ਹੈਰਾ</string>
+ <string name="tabhost_insert">ਸ਼ਾਮਲ ਕਰੋ</string>
+ <string name="alert_ok">ਠੀਕ ਹੈ</string>
+ <string name="alert_cancel">ਰੱਦ ਕਰੋ</string>
+ <string name="display_language_summary">ਮੂਲ ਦਿਖਾਉਣ ਵਾਲੀ ਭਾਸ਼ਾ ਵਜੋਂ ਸੈੱਟ ਕਰੋ</string>
+ <string name="about_privacy_policy">ਪਰਦੇਦਾਰੀ ਨੀਤੀ</string>
+ <string name="default_document_name">ਬਿਨਾਂ-ਨਾਂ</string>
+ <string name="select_photo">ਫੋਟੋ ਚੁਣੋ</string>
+ <string name="unable_to_export_pdf">PDF ਵਜੋਂ ਐਕਸਪੋਰਟ ਕਰਨ ਲਈ ਅਸਮਰੱਥ</string>
+ <string name="error">ਗਲਤੀ</string>
+ <string name="enter_part_name">ਭਾਗ ਦਾ ਨਾਂ ਦਿਓ</string>
+ <string name="page">ਸਫ਼ਾ</string>
+ <string name="sheet">ਸ਼ੀਟ</string>
+ <string name="slide">ਸਲਾਈਡ</string>
+ <string name="part">ਹਿੱਸਾ</string>
+ <string name="highlight_color">ਉਭਾਰਨ ਲਈ ਰੰਗ</string>
+ <string name="font_color">ਫ਼ੋਂਟ ਦਾ ਰੰਗ</string>
+ <string name="automatic">ਆਪਣੇ-ਆਪ</string>
+ <string name="app_name">LibreOffice ਦਰਸ਼ਕ</string>
+ <string name="app_name_settings">LibreOffice ਦਰਸ਼ਕ ਸੈਟਿੰਗਾਂ</string>
+ <string name="app_version">ਵਰਜ਼ਨ: %1$s&lt;br&gt;ਬਿਲਡ ID: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="search_find_next">ਅੱਗੇ ਲੱਭੋ</string>
+ <string name="pref_experimental_editing_summary">ਤਜਰਬੇ ਅਧੀਨ ਸੋਧ ਢੰਗ ਨੂੰ ਸਮਰੱਥ ਕਰੋ। ਇਸ ਨੂੰ ਆਪਣੀ ਜੁੰਮੇਵਾਰੀ ਉੱਤੇ ਵਰਤੋਂ।</string>
+ <string name="search_find_previous">ਪਿੱਛੇ ਲੱਭੋ</string>
+ <string name="file_icon_desc">ਫਾਈਲ-ਆਈਕਾਨ</string>
+ <string name="message_saving">…ਦਸਤਾਵੇਜ਼ ਸੰਭਾਲਿਆ ਜਾ ਰਿਹਾ ਹੈ</string>
+ <string name="save_alert_dialog_title">ਕੀ ਬੰਦ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਦਸਤਾਵੇਜ਼ ਨੂੰ ਸੰਭਾਲਣਾ ਹੈ\?</string>
+ <string name="action_text_copied">ਲਿਖਤ ਨੂੰ ਕਲਿੱਪਬੋਰਡ ਵਿੱਚ ਕਾਪੀ ਗਿਆ</string>
+ <string name="action_add_slide">ਸਲਾਈਡ ਜੋੜੋ</string>
+ <string name="take_photo">ਫੋਟੋ ਲਵੋ</string>
+ <string name="action_rename_worksheet">ਵਰਕਸ਼ੀਟ ਦਾ ਨਾਂ ਬਦਲੋ</string>
+ <string name="tabhost_style">ਸਟਾਈਲ</string>
+ <string name="display_language">ਦਿਖਾਉਣ ਲਈ ਭਾਸ਼ਾ</string>
+ <string name="pdf_export_finished">PDF ਐਕਸਪੋਰਟ ਕਰਨਾ ਪੂਰਾ ਹੋਇਆ</string>
+ <string name="unable_to_save">ਫਾਈਲ ਸੰਭਾਲਣ ਲਈ ਅਸਮਰੱਥ</string>
+ <string name="action_rename_slide">ਸਲਾਈਡ ਦਾ ਨਾਂ ਬਦਲੋ</string>
+ <string name="calc_optimal_length">ਅਨੁਕੂਲ ਲੰਬਾਈ</string>
+ <string name="calc_optimal_height">ਉਚਾਈ ਅਨੁਕੂਲ ਕਰੋ</string>
+ <string name="compress_photo_title">ਕੀ ਤੁਸੀਂ ਫੋਟੋ ਨੂੰ ਕੰਪਰੈੱਸ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ\?</string>
+ <string name="action_UNO_commands">UNO ਕਮਾਂਡ ਭੇਜੋ</string>
+ <string name="UNO_commands_string_hint">UNO ਕਮਾਂਡ</string>
+ <string name="UNO_commands_string_type_hint">ਕਿਸਮ</string>
+ <string name="UNO_commands_string_value_hint">ਮੁੱਲ</string>
+ <string name="UNO_commands_string_parent_value_hint">ਮੁੱਢਲਾ ਮੁੱਲ</string>
+ <string name="current_uno_command">ਮੌਜੂਦਾ UNO ਕਮਾਂਡ</string>
+ <string name="name_already_used">ਦਿੱਤਾ ਨਾਂ ਪਹਿਲਾਂ ਹੀ ਵਰਤਿਆ ਗਿਆ ਹੈ।</string>
+ <string name="part_name_changed">ਪਾਰਟ ਦਾ ਨਾਂ ਬਦਲਿਆ ਜਾ ਚੁੱਕਾ ਹੈ।</string>
+ <string name="part_deleted">ਪਾਰਟ ਨੂੰ ਹਟਾਇਆ ਜਾ ਚੁੱਕਾ ਹੈ।</string>
+ <string name="bmp_null">bmp ਨਲ ਹੈ!</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-pl/strings.xml b/android/source/res/values-pl/strings.xml
new file mode 100644
index 000000000000..01cb0a597d89
--- /dev/null
+++ b/android/source/res/values-pl/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="about_license">Pokaż licencję</string>
+ <string name="pref_experimental_editing_summary">Włącz eksperymentalny tryb edycji. Używaj na własne ryzyko.</string>
+ <string name="action_rename_slide">Zmień nazwę slajdu</string>
+ <string name="calc_optimal_height">Optymalna wysokość</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="app_description">LibreOffice Viewer to przeglądarka dokumentów oparta na LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="about_privacy_policy">Polityka prywatności</string>
+ <string name="create_file">Utwórz nowy plik</string>
+ <string name="new_textdocument">Nowy dokument tekstowy</string>
+ <string name="new_presentation">Nowa prezentacja</string>
+ <string name="new_spreadsheet">Nowy arkusz kalkulacyjny</string>
+ <string name="new_drawing">Nowy rysunek</string>
+ <string name="about_notice">Pokaż uwagi</string>
+ <string name="select_file_to_open">Wybierz plik do otwarcia</string>
+ <string name="search_find_previous">Znajdź poprzednie</string>
+ <string name="file_icon_desc">ikona pliku</string>
+ <string name="title_recents">Ostatnie pliki</string>
+ <string name="title_browser">Wszystkie pliki</string>
+ <string name="pref_category_general">Ogólne</string>
+ <string name="pref_experimental_editing">Tryb eksperymentalny</string>
+ <string name="pref_developer_mode">Tryb programisty</string>
+ <string name="pref_developer_mode_summary">Włącz tryb programisty, w którym możesz wysyłać polecenia UNO w aplikacji. Używaj na własne ryzyko.</string>
+ <string name="action_parts">Części</string>
+ <string name="action_settings">Ustawienia</string>
+ <string name="action_keyboard">Pokaż klawiaturę</string>
+ <string name="action_about">O aplikacji</string>
+ <string name="action_fromat">Włącz formatowanie</string>
+ <string name="action_search">Szukaj</string>
+ <string name="action_UNO_commands">Wyślij polecenie UNO</string>
+ <string name="message_saved">Zapisywanie ukończone</string>
+ <string name="message_saving">Zapisywanie dokumentu…</string>
+ <string name="message_saving_failed">Zapisanie dokumentu nie powiodło się.</string>
+ <string name="password">Hasło</string>
+ <string name="action_undo">Cofnij</string>
+ <string name="action_redo">Ponów</string>
+ <string name="save_alert_dialog_title">Zapisać dokument przed zamknięciem\?</string>
+ <string name="save_document">ZAPISZ</string>
+ <string name="action_cancel">Anuluj</string>
+ <string name="no_save_document">NIE</string>
+ <string name="action_add_slide">Dodaj slajd</string>
+ <string name="slideshow_action_back">Wstecz</string>
+ <string name="calc_insert_before">Wstaw</string>
+ <string name="calc_hide">Ukryj</string>
+ <string name="calc_show">Pokaż</string>
+ <string name="calc_adjust_length">Dostosuj długość</string>
+ <string name="calc_adjust_height">Dostosuj wysokość</string>
+ <string name="calc_optimal_length">Optymalna długość</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="action_add_worksheet">Dodaj arkusz</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="action_pwd_dialog_cancel">Anuluj</string>
+ <string name="take_photo">Zrób zdjęcie</string>
+ <string name="select_photo">Wybierz zdjęcie</string>
+ <string name="select_photo_title">Wybierz obraz</string>
+ <string name="no_camera_found">Nie znaleziono aparatu</string>
+ <string name="compress_photo_smallest_size">Najmniejszy rozmiar</string>
+ <string name="compress_photo_medium_size">Średni rozmiar</string>
+ <string name="compress_photo_max_quality">Maksymalna jakość</string>
+ <string name="compress_photo_no_compress">Nie kompresuj</string>
+ <string name="compress_photo_title">Czy chcesz skompresować zdjęcie\?</string>
+ <string name="action_copy">Kopiuj</string>
+ <string name="calc_optimal_length_default_text">Wpisz dodatkową długość w setnych/mm</string>
+ <string name="action_pwd_dialog_title">Wpisz hasło</string>
+ <string name="action_cut">Wytnij</string>
+ <string name="action_back">Wstecz</string>
+ <string name="insert_table">Wstaw tabelę</string>
+ <string name="select_insert_options">Wybierz opcje wstawiania:</string>
+ <string name="select_delete_options">Wybierz opcje usuwania:</string>
+ <string name="action_rename_worksheet">Zmień nazwę arkusza</string>
+ <string name="action_delete_worksheet">Usuń arkusz</string>
+ <string name="action_delete_slide">Usuń slajd</string>
+ <string name="name_already_used">Podana nazwa jest już używana.</string>
+ <string name="part_name_changed">Nazwa części została zmieniona.</string>
+ <string name="UNO_commands_string_hint">Polecenie UNO</string>
+ <string name="UNO_commands_string_type_hint">Typ</string>
+ <string name="UNO_commands_string_parent_value_hint">Wartość nadrzędna</string>
+ <string name="action_exportToPDF">Eksportuj do PDF</string>
+ <string name="action_print">Drukuj</string>
+ <string name="tabhost_character">Znak</string>
+ <string name="tabhost_paragraph">Akapit</string>
+ <string name="tabhost_insert">Wstaw</string>
+ <string name="tabhost_style">Styl</string>
+ <string name="alert_ok">OK</string>
+ <string name="alert_cancel">Anuluj</string>
+ <string name="display_language_summary">Ustaw domyślny język wyświetlania</string>
+ <string name="display_language">Język wyświetlania</string>
+ <string name="pdf_export_finished">Zakończono eksport do PDF</string>
+ <string name="unable_to_export_pdf">Nie można wyeksportować do PDF</string>
+ <string name="unable_to_save">Nie można zapisać pliku</string>
+ <string name="error">Błąd</string>
+ <string name="bmp_null">BMP jest zerowy!</string>
+ <string name="page">Strona</string>
+ <string name="sheet">Arkusz</string>
+ <string name="slide">Slajd</string>
+ <string name="part">Część</string>
+ <string name="highlight_color">Kolor wyróżnienia</string>
+ <string name="font_color">Kolor czcionki</string>
+ <string name="app_vendor">To wydanie zostało dostarczone przez $VENDOR.</string>
+ <string name="action_save_as">Zapisz jako…</string>
+ <string name="action_presentation">Pokaz slajdów</string>
+ <string name="calc_delete">Usuń</string>
+ <string name="part_deleted">Część została usunięta.</string>
+ <string name="current_uno_command">Aktualne polecenie UNO</string>
+ <string name="enter_part_name">Wpisz nazwę części</string>
+ <string name="calc_optimal_width">Optymalna szerokość</string>
+ <string name="app_name_settings">Ustawienia LibreOffice Viewer</string>
+ <string name="app_version">Wersja: %1$s&lt;br&gt;Identyfikator kompilacji: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="readonly_file">Ten plik jest tylko do odczytu.</string>
+ <string name="default_document_name">Bez tytułu</string>
+ <string name="search_find_next">Znajdź następne</string>
+ <string name="action_save">Zapisz</string>
+ <string name="calc_adjust_width">Dostosuj szerokość</string>
+ <string name="UNO_commands_string_value_hint">Wartość</string>
+ <string name="calc_alert_double_click_optimal_length">Wskazówka: dwukrotne stuknięcie nagłówka ustawia optymalną szerokość/wysokość.</string>
+ <string name="action_paste">Wklej</string>
+ <string name="action_text_copied">Tekst skopiowano do schowka</string>
+ <string name="automatic">Automatyczny</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-pt-rBR/strings.xml b/android/source/res/values-pt-rBR/strings.xml
new file mode 100644
index 000000000000..36045ea672e9
--- /dev/null
+++ b/android/source/res/values-pt-rBR/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Leitor de LibreOffice</string>
+ <string name="app_name_settings">Configuração do leitor de LibreOffice</string>
+ <string name="app_description">Esta aplicação é um leitor de documentos baseado no LibreOffice.</string>
+ <string name="app_credits">https://pt-br.libreoffice.org</string>
+ <string name="app_vendor">Esta versão foi fornecida por $VENDOR.</string>
+ <string name="readonly_file">Este arquivo é somente leitura.</string>
+ <string name="about_license">Mostrar Licença</string>
+ <string name="about_notice">Mostar aviso</string>
+ <string name="new_textdocument">Novo documento de texto</string>
+ <string name="new_presentation">Nova apersentação</string>
+ <string name="new_spreadsheet">Nova planilha</string>
+ <string name="new_drawing">Novo desenho</string>
+ <string name="default_document_name">Sem título</string>
+ <string name="file_icon_desc">Ícone de arquivo</string>
+ <string name="title_recents">Arquivos recentes</string>
+ <string name="title_browser">Todos os arquivos</string>
+ <string name="pref_category_general">Geral</string>
+ <string name="pref_experimental_editing">Modo experimental</string>
+ <string name="pref_developer_mode">Modo de desenvolvimento</string>
+ <string name="app_version">Versão: %1$s&lt;br&gt;ID da montagem: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="select_file_to_open">Selecione o arquivo a abrir</string>
+ <string name="pref_experimental_editing_summary">Ativar o modo de edição experimental. Use por sua conta e risco.</string>
+ <string name="pref_developer_mode_summary">Ativar o modo de desenvolvedor para enviar comandos UNO dentro da aplicação. Use por sua conta e risco.</string>
+ <string name="message_saving">Salvando o arquivo…</string>
+ <string name="action_about">Sobre</string>
+ <string name="action_parts">Partes</string>
+ <string name="action_settings">Confirgurações</string>
+ <string name="action_keyboard">Mostrar teclado</string>
+ <string name="action_save">Salvar</string>
+ <string name="action_save_as">Salvar como…</string>
+ <string name="action_fromat">Ativar formato</string>
+ <string name="action_search">Pesquisar</string>
+ <string name="action_UNO_commands">Enviar comando UNO</string>
+ <string name="message_saved">Arquivo salvo</string>
+ <string name="message_saving_failed">Não foi possível salvar o documento.</string>
+ <string name="about_privacy_policy">Política de privacidade</string>
+ <string name="create_file">Criar um arquivo</string>
+ <string name="search_find_next">Localizar próxima</string>
+ <string name="search_find_previous">Localizar anterior</string>
+ <string name="password">Senha</string>
+ <string name="action_undo">Desfazer</string>
+ <string name="action_redo">Refazer</string>
+ <string name="save_document">SALVAR</string>
+ <string name="action_cancel">Cancelar</string>
+ <string name="no_save_document">NÃO</string>
+ <string name="action_presentation">Apresentação de slides</string>
+ <string name="action_add_slide">Adicionar slide</string>
+ <string name="slideshow_action_back">Voltar</string>
+ <string name="calc_insert_before">Inserir</string>
+ <string name="calc_delete">Excluir</string>
+ <string name="calc_hide">Ocultar</string>
+ <string name="calc_show">Mostrar</string>
+ <string name="calc_optimal_length">Tamanho ideal</string>
+ <string name="calc_adjust_length">Ajustar tamanho</string>
+ <string name="calc_adjust_height">Ajustar altura</string>
+ <string name="calc_adjust_width">Ajustar largura</string>
+ <string name="calc_optimal_height">Altura ideal</string>
+ <string name="calc_optimal_width">Largura ideal</string>
+ <string name="calc_optimal_length_confirm">OK</string>
+ <string name="save_alert_dialog_title">Salvar documento antes de fechar\?</string>
+ <string name="action_add_worksheet">Adicionar planilha</string>
+ <string name="action_pwd_dialog_OK">OK</string>
+ <string name="calc_optimal_length_default_text">Insira o comprimento extra em centésimos de milímetro.</string>
+ <string name="calc_alert_double_click_optimal_length">Dica: tocar duas vezes no cabeçalho define a altura/largura ideal.</string>
+ <string name="part_name_changed">O nome da parte foi alterado.</string>
+ <string name="action_pwd_dialog_cancel">Cancelar</string>
+ <string name="action_pwd_dialog_title">Digite a senha</string>
+ <string name="take_photo">Fotografar</string>
+ <string name="select_photo">Selecionar foto</string>
+ <string name="select_photo_title">Selecionar figura</string>
+ <string name="no_camera_found">Sem câmera disponível</string>
+ <string name="compress_photo_smallest_size">Menor tamanho</string>
+ <string name="compress_photo_medium_size">Tamanho médio</string>
+ <string name="compress_photo_max_quality">Qualidade máxima</string>
+ <string name="compress_photo_no_compress">Não comprimir</string>
+ <string name="compress_photo_title">Deseja comprimir a foto\?</string>
+ <string name="action_copy">Copiar</string>
+ <string name="action_paste">Colar</string>
+ <string name="action_cut">Cortar</string>
+ <string name="action_back">Voltar</string>
+ <string name="action_text_copied">Teto copiado para área de transferência</string>
+ <string name="insert_table">Inserir tabela</string>
+ <string name="select_insert_options">Selecionar opções para inserir:</string>
+ <string name="select_delete_options">Selecionar opções para excluir:</string>
+ <string name="action_rename_worksheet">Renomear planilha</string>
+ <string name="action_delete_worksheet">Excluir planilha</string>
+ <string name="action_delete_slide">Excluir slide</string>
+ <string name="name_already_used">O nome já existe.</string>
+ <string name="part_deleted">A parte foi excluída.</string>
+ <string name="UNO_commands_string_hint">Comando UNO</string>
+ <string name="UNO_commands_string_type_hint">Tipo</string>
+ <string name="UNO_commands_string_value_hint">Valor</string>
+ <string name="UNO_commands_string_parent_value_hint">Valor superior</string>
+ <string name="action_exportToPDF">Exportar em PDF</string>
+ <string name="action_print">Imprimir</string>
+ <string name="tabhost_character">Caractere</string>
+ <string name="tabhost_paragraph">Parágrafo</string>
+ <string name="tabhost_insert">Inserir</string>
+ <string name="tabhost_style">Estilo</string>
+ <string name="alert_ok">OK</string>
+ <string name="alert_cancel">Cancelar</string>
+ <string name="current_uno_command">Comando UNO atual</string>
+ <string name="display_language">Exibir idioma</string>
+ <string name="display_language_summary">Definir o idioma padrão de exibição</string>
+ <string name="unable_to_export_pdf">Não foi possível exportar em PDF</string>
+ <string name="error">Erro</string>
+ <string name="enter_part_name">Digite um nome para a parte</string>
+ <string name="bmp_null">Bmp é nulo!</string>
+ <string name="page">Página</string>
+ <string name="sheet">Planilha</string>
+ <string name="slide">Slide</string>
+ <string name="part">Parte</string>
+ <string name="highlight_color">Cor de destaque</string>
+ <string name="font_color">Cor da fonte</string>
+ <string name="automatic">Automático</string>
+ <string name="pdf_export_finished">Exportação em PDF terminada</string>
+ <string name="unable_to_save">Não foi possível salvar o arquivo</string>
+ <string name="action_rename_slide">Renomear slide</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-pt/strings.xml b/android/source/res/values-pt/strings.xml
new file mode 100644
index 000000000000..018fb3e8c575
--- /dev/null
+++ b/android/source/res/values-pt/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="pdf_export_finished">Exportação PDF terminada</string>
+ <string name="pref_developer_mode_summary">Ativa o modo de desenvolvedor para enviar comandos UNO na aplicação. Use por sua conta e risco.</string>
+ <string name="app_description">O visualizador LibreOffice é baseado no LibreOffice.</string>
+ <string name="calc_show">Mostrar</string>
+ <string name="pref_developer_mode">Modo de desenvolvimento</string>
+ <string name="action_pwd_dialog_cancel">Cancelar</string>
+ <string name="create_file">Criar novo ficheiro</string>
+ <string name="slide">Diapositivo</string>
+ <string name="part_name_changed">Parte do nome foi alterado.</string>
+ <string name="compress_photo_max_quality">Qualidade máxima</string>
+ <string name="calc_hide">Ocultar</string>
+ <string name="action_UNO_commands">Enviar comando UNO</string>
+ <string name="default_document_name">sem nome</string>
+ <string name="action_about">Acerca</string>
+ <string name="action_fromat">Ativar formato</string>
+ <string name="password">Palavra-passe</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="select_insert_options">Selecione as opções de inserção:</string>
+ <string name="UNO_commands_string_type_hint">Tipo</string>
+ <string name="current_uno_command">Comando UNO atual</string>
+ <string name="slideshow_action_back">Recuar</string>
+ <string name="bmp_null">Bmp é nulo!</string>
+ <string name="action_paste">Colar</string>
+ <string name="action_pwd_dialog_OK">Aceitar</string>
+ <string name="save_document">Guardar</string>
+ <string name="calc_adjust_length">Ajustar tamanho</string>
+ <string name="new_spreadsheet">Nova folha de cálculo</string>
+ <string name="part">Parte</string>
+ <string name="select_file_to_open">Selecione o ficheiro a abrir</string>
+ <string name="unable_to_export_pdf">Não foi possível exportar para PDF</string>
+ <string name="action_save_as">Guardar como…</string>
+ <string name="save_alert_dialog_title">Guardar documento antes de fechar\?</string>
+ <string name="font_color">Cor do tipo de letra</string>
+ <string name="action_rename_worksheet">Mudar nome da folha</string>
+ <string name="message_saving_failed">Não foi possível guardar o documento.</string>
+ <string name="calc_optimal_length">Tamanho ideal</string>
+ <string name="enter_part_name">Introduza um nome</string>
+ <string name="new_drawing">Novo desenho</string>
+ <string name="automatic">Automático</string>
+ <string name="action_delete_slide">Eliminar diapositivo</string>
+ <string name="action_redo">Refazer</string>
+ <string name="action_cut">Cortar</string>
+ <string name="file_icon_desc">ícone</string>
+ <string name="title_recents">Recentes</string>
+ <string name="page">Página</string>
+ <string name="calc_insert_before">Inserir</string>
+ <string name="calc_optimal_length_default_text">Introduza o comprimento extra em centésimos de milímetro.</string>
+ <string name="message_saving">A guardar…</string>
+ <string name="tabhost_style">Estilo</string>
+ <string name="select_photo_title">Selecionar imagem</string>
+ <string name="calc_optimal_width">Largura ideal</string>
+ <string name="action_delete_worksheet">Eliminar folha</string>
+ <string name="no_save_document">Não</string>
+ <string name="highlight_color">Cor de destaque</string>
+ <string name="new_textdocument">Novo documento de texto</string>
+ <string name="action_print">Imprimir</string>
+ <string name="calc_adjust_width">Ajustar largura</string>
+ <string name="action_add_worksheet">Adicionar folha</string>
+ <string name="new_presentation">Nova apresentação</string>
+ <string name="tabhost_paragraph">Parágrafo</string>
+ <string name="action_back">Recuar</string>
+ <string name="pref_experimental_editing">Modo experimental</string>
+ <string name="calc_delete">Eliminar</string>
+ <string name="part_deleted">A parte foi eliminada.</string>
+ <string name="action_undo">Desfazer</string>
+ <string name="app_vendor">Esta versão foi disponibilizada por $VENDOR.</string>
+ <string name="action_pwd_dialog_title">Introduza a palavra-passe</string>
+ <string name="calc_optimal_length_confirm">Aceitar</string>
+ <string name="action_parts">Partes</string>
+ <string name="compress_photo_medium_size">Tamanho médio</string>
+ <string name="display_language_summary">Defina o idioma de exibição padrão</string>
+ <string name="select_delete_options">Selecione as opções de eliminação:</string>
+ <string name="pref_category_general">Geral</string>
+ <string name="action_text_copied">Teto copiado para a área de transferência</string>
+ <string name="action_exportToPDF">Exportar para PDF</string>
+ <string name="action_rename_slide">Mudar nome do diapositivo</string>
+ <string name="action_keyboard">Mostrar teclado</string>
+ <string name="about_privacy_policy">Política de privacidade</string>
+ <string name="action_presentation">Apresentação</string>
+ <string name="UNO_commands_string_parent_value_hint">Valor superior</string>
+ <string name="compress_photo_smallest_size">Menor tamanho</string>
+ <string name="select_photo">Selecionar foto</string>
+ <string name="compress_photo_no_compress">Não comprimir</string>
+ <string name="action_copy">Copiar</string>
+ <string name="tabhost_insert">Inserir</string>
+ <string name="action_search">Pesquisar</string>
+ <string name="message_saved">Guardado</string>
+ <string name="no_camera_found">Câmara não encontrada</string>
+ <string name="error">Erro</string>
+ <string name="app_name_settings">Definições</string>
+ <string name="name_already_used">Este nome já está a ser utilizado.</string>
+ <string name="action_save">Guardar</string>
+ <string name="UNO_commands_string_hint">Comando UNO</string>
+ <string name="alert_ok">Aceitar</string>
+ <string name="UNO_commands_string_value_hint">Valor</string>
+ <string name="action_settings">Definições</string>
+ <string name="sheet">Folha</string>
+ <string name="compress_photo_title">Deseja comprimir a foto\?</string>
+ <string name="app_version">Versão: %1$s&lt;br&gt;ID da compilação: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_license">Mostrar licença</string>
+ <string name="title_browser">Todos os ficheiros</string>
+ <string name="take_photo">Obter foto</string>
+ <string name="unable_to_save">Não foi possível guardar o ficheiro</string>
+ <string name="app_name">Visualizador LibreOffice</string>
+ <string name="insert_table">Inserir tabela</string>
+ <string name="action_add_slide">Adicionar diapositivo</string>
+ <string name="action_cancel">Cancelar</string>
+ <string name="calc_adjust_height">Ajustar altura</string>
+ <string name="display_language">Idioma de exibição</string>
+ <string name="search_find_next">Localizar seguinte</string>
+ <string name="search_find_previous">Localizar anterior</string>
+ <string name="pref_experimental_editing_summary">Ativar o modo de edição experimental. Use por sua conta e risco.</string>
+ <string name="readonly_file">Este ficheiro é apenas de leitura.</string>
+ <string name="about_notice">Mostar aviso</string>
+ <string name="alert_cancel">Cancelar</string>
+ <string name="calc_optimal_height">Altura ideal</string>
+ <string name="tabhost_character">Carácter</string>
+ <string name="calc_alert_double_click_optimal_length">Dica: dois toques no cabeçalho define a altura/largura ideal.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-sk/strings.xml b/android/source/res/values-sk/strings.xml
new file mode 100644
index 000000000000..b83ec58936b9
--- /dev/null
+++ b/android/source/res/values-sk/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_description">LibreOffice Viewer je prehliadač dokumentov založený na LibreOffice.</string>
+ <string name="default_document_name">bez názvu</string>
+ <string name="action_about">Info</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="new_spreadsheet">Nový tabuľkový dokument</string>
+ <string name="select_file_to_open">Vyberte súbor, ktorý chcete otvoriť</string>
+ <string name="new_drawing">Nová kresba</string>
+ <string name="title_recents">Posledné súbory</string>
+ <string name="new_textdocument">Nový textový dokument</string>
+ <string name="new_presentation">Nová prezentácia</string>
+ <string name="app_vendor">Dodávateľom tohto produktu je $VENDOR.</string>
+ <string name="pref_category_general">Všeobecné</string>
+ <string name="app_name_settings">Nastavenia LibreOffice Viewer</string>
+ <string name="app_version">Verzia: %1$s&lt;br&gt;ID zostavenia: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="about_license">Zobraziť licenciu</string>
+ <string name="title_browser">Všetky súbory</string>
+ <string name="app_name">LibreOffice Viewer</string>
+ <string name="readonly_file">Táto súbor je len na čítanie.</string>
+ <string name="about_notice">Zobraziť oznam</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-sl/strings.xml b/android/source/res/values-sl/strings.xml
new file mode 100644
index 000000000000..f245e39bb429
--- /dev/null
+++ b/android/source/res/values-sl/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name_settings">Nastavitve Pregledovalnika LibreOffice</string>
+ <string name="app_version">Različica: %1$s&lt;br&gt;ID gradnje: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">Pregledovalnik LibreOffice je pregledovalnik dokumentov, zasnovan na LibreOffice.</string>
+ <string name="app_credits">https://sl.libreoffice.org</string>
+ <string name="readonly_file">Ta datoteka je samo za branje.</string>
+ <string name="about_license">Pokaži dovoljenje</string>
+ <string name="new_drawing">Nova risba</string>
+ <string name="create_file">Ustvari novo datoteko</string>
+ <string name="new_presentation">Nova predstavitev</string>
+ <string name="new_spreadsheet">Nova preglednica</string>
+ <string name="default_document_name">neimenovano</string>
+ <string name="new_textdocument">Nov besedilni dokument</string>
+ <string name="about_notice">Pokaži obvestilo</string>
+ <string name="about_privacy_policy">Politika zasebnosti</string>
+ <string name="title_browser">Vse datoteke</string>
+ <string name="pref_experimental_editing">Poskusni način</string>
+ <string name="action_save">Shrani</string>
+ <string name="action_settings">Nastavitve</string>
+ <string name="title_recents">Nedavne datoteke</string>
+ <string name="message_saved">Shranjevanje dokončano</string>
+ <string name="action_save_as">Shrani kot …</string>
+ <string name="action_about">O programu</string>
+ <string name="pref_developer_mode">Razvijalski način</string>
+ <string name="action_keyboard">Pokaži tipkovnico</string>
+ <string name="message_saving_failed">Shranjevanje dokumenta je spodletelo.</string>
+ <string name="action_parts">Deli</string>
+ <string name="action_UNO_commands">Pošlji ukaz UNO</string>
+ <string name="file_icon_desc">Ikona datoteke</string>
+ <string name="action_search">Išči</string>
+ <string name="action_fromat">Omogoči oblikovanje</string>
+ <string name="pref_developer_mode_summary">Omogočite način za razvijalce, v katerem lahko v aplikaciji pošiljate ukaze UNO. Uporabljajte na lastno odgovornost.</string>
+ <string name="search_find_next">Najdi naslednje</string>
+ <string name="search_find_previous">Najdi prejšnje</string>
+ <string name="action_add_slide">Dodaj prosojnico</string>
+ <string name="action_cancel">Prekliči</string>
+ <string name="calc_delete">Izbriši</string>
+ <string name="action_undo">Razveljavi</string>
+ <string name="action_redo">Uveljavi</string>
+ <string name="save_document">SHRANI</string>
+ <string name="action_presentation">Projekcija</string>
+ <string name="slideshow_action_back">Nazaj</string>
+ <string name="no_save_document">NE</string>
+ <string name="calc_show">Pokaži</string>
+ <string name="calc_hide">Skrij</string>
+ <string name="action_pwd_dialog_OK">V redu</string>
+ <string name="action_pwd_dialog_cancel">Prekliči</string>
+ <string name="calc_adjust_length">Prilagodi dolžino</string>
+ <string name="calc_adjust_height">Prilagodi višino</string>
+ <string name="calc_adjust_width">Prilagodi širino</string>
+ <string name="calc_optimal_height">Optimalna višina</string>
+ <string name="calc_optimal_width">Optimalna širina</string>
+ <string name="select_photo_title">Izberite sliko</string>
+ <string name="no_camera_found">Kamere ni mogoče najti</string>
+ <string name="action_add_worksheet">Dodaj delovni list</string>
+ <string name="calc_optimal_length_default_text">Vnesite dodatno dolžino v stotinah/mm</string>
+ <string name="action_pwd_dialog_title">Vnesite geslo</string>
+ <string name="take_photo">Naredi fotografijo</string>
+ <string name="select_photo">Izberite fotografijo</string>
+ <string name="action_paste">Prilepi</string>
+ <string name="UNO_commands_string_value_hint">Vrednost</string>
+ <string name="alert_ok">V redu</string>
+ <string name="error">Napaka</string>
+ <string name="tabhost_paragraph">Odstavek</string>
+ <string name="tabhost_insert">Vstavi</string>
+ <string name="alert_cancel">Prekliči</string>
+ <string name="page">Stran</string>
+ <string name="sheet">Delovni list</string>
+ <string name="slide">Prosojnica</string>
+ <string name="insert_table">Vstavi tabelo</string>
+ <string name="action_delete_slide">Izbriši prosojnico</string>
+ <string name="action_cut">Izreži</string>
+ <string name="UNO_commands_string_type_hint">Vrsta</string>
+ <string name="tabhost_style">Slog</string>
+ <string name="display_language">Prikaži jezik</string>
+ <string name="current_uno_command">Trenutni ukaz UNO</string>
+ <string name="action_back">Nazaj</string>
+ <string name="action_print">Natisni</string>
+ <string name="tabhost_character">Znak</string>
+ <string name="compress_photo_medium_size">Srednja velikost</string>
+ <string name="compress_photo_max_quality">Najvišja kakovost</string>
+ <string name="compress_photo_no_compress">Ne stisni</string>
+ <string name="action_rename_worksheet">Preimenuj delovni list</string>
+ <string name="action_delete_worksheet">Izbriši delovni list</string>
+ <string name="compress_photo_smallest_size">Najmanjša velikost</string>
+ <string name="part_deleted">Del je bil izbrisan.</string>
+ <string name="part_name_changed">Ime dela je bilo spremenjeno.</string>
+ <string name="name_already_used">Dano ime je že v rabi.</string>
+ <string name="select_insert_options">Izberite možnosti vstavljanja:</string>
+ <string name="select_delete_options">Izberite možnosti brisanja:</string>
+ <string name="enter_part_name">Vnesite ime dela</string>
+ <string name="display_language_summary">Določite privzeti jezik za prikaz</string>
+ <string name="pdf_export_finished">Izvoz v PDF je dokončan</string>
+ <string name="unable_to_export_pdf">Izvoz v PDF ni možen</string>
+ <string name="unable_to_save">Datoteke ni mogoče shraniti</string>
+ <string name="part">Del</string>
+ <string name="UNO_commands_string_parent_value_hint">Nadrejena vrednost</string>
+ <string name="bmp_null">Bmp je ničen!</string>
+ <string name="font_color">Barva pisave</string>
+ <string name="automatic">Samodejno</string>
+ <string name="action_rename_slide">Preimenuj prosojnico</string>
+ <string name="highlight_color">Barva poudarjanja</string>
+ <string name="app_name">Pregledovalnik LibreOffice</string>
+ <string name="app_vendor">Ta izdelek je dal na voljo $VENDOR.</string>
+ <string name="pref_category_general">Splošno</string>
+ <string name="UNO_commands_string_hint">Ukaz UNO</string>
+ <string name="message_saving">Shranjevanje dokumenta …</string>
+ <string name="calc_optimal_length">Optimalna dolžina</string>
+ <string name="compress_photo_title">Ali želite stisniti fotografijo\?</string>
+ <string name="password">Geslo</string>
+ <string name="action_copy">Kopiraj</string>
+ <string name="calc_insert_before">Vstavi</string>
+ <string name="calc_optimal_length_confirm">V redu</string>
+ <string name="pref_experimental_editing_summary">Omogočite poskusni način urejanja. Uporabljajte na lastno odgovornost.</string>
+ <string name="action_exportToPDF">Izvozi v PDF</string>
+ <string name="select_file_to_open">Izberite datoteko, ki jo želite odpreti.</string>
+ <string name="save_alert_dialog_title">Ali želite shraniti dokument pred zapiranjem\?</string>
+ <string name="action_text_copied">Besedilo je kopirano v odložišče</string>
+ <string name="calc_alert_double_click_optimal_length">Namig: dvakrat tapnite glavo, da nastavite optimalno širino/višino.</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-tr/strings.xml b/android/source/res/values-tr/strings.xml
index 3bada4ded6be..d981956e988b 100644
--- a/android/source/res/values-tr/strings.xml
+++ b/android/source/res/values-tr/strings.xml
@@ -1,149 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
-
<string name="app_name">LibreOffice Görüntüleyici</string>
<string name="app_name_settings">LibreOffice Görüntüleyici Ayarları</string>
-
- <string name="app_about_name"><b>LibreOffice Görüntüleyici \'Beta\'</b></string>
- <string name="app_version">Versiyon: %1$s\nBuild ID: %2$s</string>
+ <string name="app_version">Versiyon: %1$s&lt;br&gt;Build ID: &lt;a href="https://hub.libreoffice.org/git-core/%2$s"&gt;%2$s&lt;/a&gt;</string>
<string name="app_description">LibreOffice Görüntüleyici LibreOffice tabanlı bir belge görüntüleyicisidir.</string>
<string name="app_credits">https://www.libreoffice.org</string>
<string name="app_vendor">Bu sürüm $VENDOR tarafından derlenmiştir.</string>
- <string name="temp_file_saving_disabled">Bu dosya salt okunabilir haldedir. Kaydetme devredışı.</string>
-
+ <string name="readonly_file">Bu dosya salt okunabilir haldedir.</string>
<string name="about_license">Lisansı Görüntüle</string>
<string name="about_notice">Bildiriyi Görüntüle</string>
- <string name="about_moreinfo">Daha Fazla Bilgi</string>
- <string name="back_again_to_quit">Çıkış için geri tuşuna tekrar basınız.</string>
-
<string name="new_textdocument">Yeni Kelime İşlemci</string>
<string name="new_presentation">Yeni Sunum</string>
<string name="new_spreadsheet">Yeni Hesap Tablosu</string>
<string name="new_drawing">Yeni Çizim</string>
<string name="default_document_name">adsız</string>
-
- <string name="browser_app_name">LibreOffice Tarayıcı</string>
- <string name="menu_search">Ara</string>
- <string name="list_view">Liste</string>
- <string name="grid_view">Grid</string>
- <string name="filter">Şununla filtrele:</string>
- <string name="search_not_found">Söz dizimi bulunamadı.</string>
- <string name="sort">Şununla sırala:</string>
- <string name="sort_smallest">Küçükten büyüğe</string>
- <string name="sort_largest">Büyükten küçüğe</string>
- <string name="sort_az">A-Z</string>
- <string name="sort_za">Z-A</string>
- <string name="sort_oldest">Eskiden yeniye</string>
- <string name="sort_newest">Yeniden eskiye</string>
- <string name="menu_sort_size">Boyuta Göre Sırala</string>
- <string name="menu_sort_az">Alfabetik Sırala</string>
- <string name="menu_sort_modified">Tarihe Göre Sırala</string>
- <string name="menu_preferences">Seçenekler</string>
<string name="file_icon_desc">dosya_simgesi</string>
<string name="title_recents">Son açılan dosyalar</string>
<string name="title_browser">Tüm dosyalar</string>
- <!-- Pref keys as resources ; Not currently used -->
- <string name="EXPLORER_VIEW_TYPE_KEY">EXPLORER_VIEW_TYPE</string>
- <string name="CURRENT_DIRECTORY_KEY">CURRENT_DIRECTORY</string>
- <string name="pref_category_explorer">Dosya Gezgini Ayarları</string>
<string name="pref_category_general">Genel</string>
<string name="pref_experimental_editing">Deneysel Mod</string>
<string name="pref_experimental_editing_summary">Deneysel düzenleme modunu etkinleştirin. Kullanım riski size aittir.</string>
- <string name="pref_show_hidden_files">Gizli Dosyalar ve Dizinler</string>
- <string name="pref_show_hidden_files_summary">Gizli dosyalar ve dizinleri göstermeyi etkinleştir.</string>
<string name="pref_developer_mode">Geliştirici Modu</string>
<string name="pref_developer_mode_summary">Geliştirici modunu etkinleştirerek UNO komutları gönderin. Kullanım riski size aittir.</string>
-
<string name="action_about">Hakkında</string>
<string name="action_parts">Bölümler</string>
<string name="action_settings">Ayarlar</string>
- <string name="open">Aç</string>
- <string name="share">Paylaş</string>
- <string name="share_via">Şununla paylaş</string>
-
- <!-- Document browser filters -->
- <string name="filter_everything">Hepsi</string>
- <string name="filter_documents">Kelime İşlemci</string>
- <string name="filter_spreadsheets">Hesap Tablosu</string>
- <string name="filter_presentations">Sunum</string>
- <string name="filter_drawings">Çizimler</string>
-
- <!-- Document provider names -->
- <string name="document_locations">Belge dizinleri</string>
- <string name="close_document_locations">Belge dizinlerini kapat</string>
- <string name="local_documents">Belgeler</string>
- <string name="local_file_system">Yerel dosya sistemi</string>
- <string name="external_sd_file_system">Harici SD</string>
- <string name="otg_file_system">OTG cihazı (deneysel)</string>
- <string name="owncloud">Uzak sunucu</string>
- <string name="usb_connected_configure">USB bağlantısı yapıldı, cihazınızın ayarlarını yapınız.</string>
-
- <string name="owncloud_wrong_connection">ownCloud sunucusuna bağlanılamadı. Ayarlarınızı kontrol ediniz.</string>
- <string name="owncloud_unauthorized">ownCloud sunucusuna giriş yapılamadı. Ayarlarınızı kontrol ediniz.</string>
- <string name="owncloud_unspecified_error">ownCloud sunucusuna bağlanırken belirtilmemiş bir hata oluştu. Lütfen daha sonra tekrar deneyiniz veya ayarlarınızı kontrol ediniz.</string>
-
- <string name="ext_document_provider_error">Geçersiz dizin. SD kart ayarlarınızı kontrol ediniz.</string>
- <string name="legacy_extsd_missing_error">Geçersiz dizin. SD kartınızı veya SD kart ayarlarınızı kontrol ediniz.</string>
- <string name="otg_missing_error">Geçersiz dizin. OTG cihazınızı veya OTG cihazı ayarlarınızı kontrol ediniz.</string>
-
<!-- Edit action names -->
- <string name="action_bold">Kalın</string>
- <string name="action_underline">Altı çizgili</string>
- <string name="action_italic">Yana yatık</string>
- <string name="action_strikeout">Üzeri çizgili</string>
<string name="action_keyboard">Klaveyi göster</string>
<string name="action_save">Kaydet</string>
<string name="action_fromat">Biçimlendirmeyi etkinleştir.</string>
<string name="action_search">Ara</string>
<string name="action_UNO_commands">UNO komutu yolla</string>
-
<!-- Feedback messages -->
<string name="message_saved">Kaydetme tamamlandı.</string>
<string name="message_saving">Belge kaydediliyor…</string>
- <string name="message_save_incomplete">Kayıt tamamlanmadı. Değişiklik yapıldı mı?</string>
- <string name="create_new_file_success">"Yeni dosya oluşturuldu - "</string>
- <string name="create_new_file_error">Yeni dosya oluşturma başarısız. Lütfen dosya ismini kontrol ediniz.</string>
-
- <!-- Document provider settings -->
- <string name="storage_provider_settings">Depolama sağlayıcısı ayarları</string>
- <string name="owncloud_settings">ownCloud ayarları</string>
- <string name="physical_storage_settings">Fiziksel depolama ayarları</string>
- <string name="external_sd_path">Harici SD yolu</string>
- <string name="otg_device_path">OTG cihazı yolu</string>
- <string name="otg_warning">Deneysel özellik: OTG cihazı yazılabilir ise kullanın</string>
- <string name="server_url">Sunucu URL</string>
- <string name="server_url_and_port">ownCloud sunucusu URL ve port</string>
- <string name="user_name">Kullanıcı Adı</string>
<string name="password">Parola</string>
<string name="action_undo">Geri Al</string>
<string name="action_redo">Yinele</string>
-
- <!-- Directory browser strings -->
- <string name="up_description">Üst dizin</string>
- <string name="confirm_label">Onayla</string>
- <string name="cancel_label">İptal</string>
- <string name="search_label">Git</string>
- <string name="directory_browser_label">Dizin Seç</string>
- <string name="bad_directory">Geçersiz dizin</string>
- <string name="current_dir">Şuan ki dizin: %1$s</string>
-
<!-- Save Alert dialog strings -->
<string name="save_alert_dialog_title">Değişiklikleri kaydetmek istiyor musunuz?</string>
<string name="save_document">Kaydet</string>
<string name="action_cancel">İptal</string>
<string name="no_save_document">Hayır</string>
-
- <!-- Create New Document Dialog Strings -->
- <string name="create_new_document_title">Dosya ismi girin</string>
- <string name="action_create">OLUŞTUR</string>
-
<!-- Presentation Mode Strings -->
<string name="action_presentation">Slayt Gösterisi</string>
<string name="action_add_slide">Slayt Ekle</string>
- <string name="alert_copy_svg_slide_show_to_clipboard">Cihazınız uygulama içi slayt gösterisini desteklemiyor. Sunumu panoya kopyaladık. Lütfen ev tuşuna basıp modern bir tarayıcı açıp arama çubuğuna yapıştırın ve sunumu görüntüleyin.</string>
- <string name="alert_copy_svg_slide_show_to_clipboard_dismiss">Tamam</string>
<string name="slideshow_action_back">Geri</string>
-
<!-- Calc Header Menu Strings -->
<string name="calc_insert_before">Ekle</string>
<string name="calc_delete">Sil</string>
@@ -159,12 +61,10 @@
<string name="calc_optimal_length_default_text">Extra uzunluk giriniz: 100th/mm</string>
<string name="calc_alert_double_click_optimal_length">İpucu: Başlığa çift dokunuş en iyi uzunluk ve genişliği ayarlar.</string>
<string name="action_add_worksheet">Hesap Tablosu Ekle</string>
-
<!-- Password dialog strings -->
<string name="action_pwd_dialog_OK">Tamam</string>
<string name="action_pwd_dialog_cancel">İptal</string>
<string name="action_pwd_dialog_title">Lütfen parola giriniz.</string>
-
<!-- Insert Image Strings -->
<string name="take_photo">Fotoğraf Çek</string>
<string name="select_photo">Fotoğraf Seç</string>
@@ -175,7 +75,6 @@
<string name="compress_photo_max_quality">Maksimum Kalite</string>
<string name="compress_photo_no_compress">Sıkıştırma yapma</string>
<string name="compress_photo_title">Fotoğrafı sıkıştırmak ister misiniz?</string>
-
<!-- Clipboard Actions -->
<string name="action_copy">Kopyala</string>
<string name="action_paste">Yapıştır</string>
@@ -203,7 +102,6 @@
<item>Sütun Sil</item>
<item>Tablo Sil</item>
</string-array>
-
<!-- UNO cmd controller Strings -->
<string name="UNO_commands_string_hint">UNO Komutu</string>
<string name="UNO_commands_string_type_hint">Tip</string>
@@ -217,23 +115,13 @@
<string name="tabhost_style">Biçim</string>
<string name="alert_ok">Tamam</string>
<string name="alert_cancel">İptal</string>
- <string name="unable_to_go_further">Daha fazla ilerlenemiyor.</string>
<string name="current_uno_command">Şuan ki UNO komutu</string>
- <string name="pref_sort_summary">Dosyaların nasıl sıralanacağını seçiniz. A-Z, Z-A ya da boyuta göre.</string>
- <string name="pref_viewmode_summary">Dosyaları grid veya liste şeklinde görüntüle.</string>
- <string name="pref_file_explorer_title">Dosya Gezgini</string>
- <string name="pref_sort_title">Dosya Sıralaması</string>
- <string name="pref_filter_title">Varsayılan Dosya Filtrelemesi</string>
- <string name="pref_filter_summary">Varsayılan dosya filtrelemesini seç</string>
<string name="display_language">Uygulama Dili</string>
<string name="display_language_summary">Varsayılan dili değiştir</string>
<string name="unable_to_export_pdf">Pdf dışa aktarılamıyor.</string>
- <string name="pdf_exported_at">Şu konumda pdf\'e aktarıldı: </string>
- <string name="printing_not_supported">Cihazınız yazdırmayı desteklemiyor.</string>
<string name="error">Hata</string>
<string name="enter_part_name">Bölüm ismi girin.</string>
<string name="bmp_null">Bmp boş!</string>
- <string name="directory_not_saved">Dizin kaydedilmedi.</string>
<string name="page">Sayfa</string>
<string name="sheet">Tablo</string>
<string name="slide">Slayt</string>
@@ -241,4 +129,14 @@
<string name="highlight_color">Vurgulama Rengi</string>
<string name="font_color">Metin Rengi</string>
<string name="action_rename_slide">Slaytı yeniden adlandır</string>
-</resources>
+ <string name="about_privacy_policy">Gizlilik Politikası</string>
+ <string name="action_save_as">Farklı Kaydet…</string>
+ <string name="automatic">Otomatik</string>
+ <string name="create_file">Yeni Dosya Oluştur</string>
+ <string name="search_find_next">Sonrakini Bul</string>
+ <string name="search_find_previous">Öncekini Bul</string>
+ <string name="pdf_export_finished">PDF dışa aktarıldı</string>
+ <string name="unable_to_save">Dosya kaydedilemiyor</string>
+ <string name="message_saving_failed">Belge kaydedilemedi.</string>
+ <string name="select_file_to_open">Açılacak dosyayı seçin</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-uk/strings.xml b/android/source/res/values-uk/strings.xml
new file mode 100644
index 000000000000..e6048cc3dff0
--- /dev/null
+++ b/android/source/res/values-uk/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Оглядач LibreOffice</string>
+ <string name="app_description">Оглядач LibreOffice - це програма, яка може відкривати документи LibreOffice.</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">Цей випуск постачає $VENDOR.</string>
+ <string name="readonly_file">Цей файл лише для читання.</string>
+ <string name="about_license">Показати ліцензію</string>
+ <string name="about_notice">Показати Примітки</string>
+ <string name="new_presentation">Нова презентація</string>
+ <string name="new_spreadsheet">Нова електронна таблиця</string>
+ <string name="new_drawing">Новий рисунок</string>
+ <string name="default_document_name">без назви</string>
+ <string name="select_file_to_open">Оберіть файл для відкриття</string>
+ <string name="file_icon_desc">піктограма</string>
+ <string name="create_file">Створити новий файл</string>
+ <string name="search_find_next">Знайти наступне</string>
+ <string name="search_find_previous">Знайти попереднє</string>
+ <string name="title_browser">Всі файли</string>
+ <string name="pref_category_general">Загальне</string>
+ <string name="pref_developer_mode">Режим розробника</string>
+ <string name="pref_developer_mode_summary">Активувати режим розробника, де у межах додатка можна надсилати команди UNO. Використовуйте на власний ризик.</string>
+ <string name="action_about">Про програму</string>
+ <string name="action_parts">Частини</string>
+ <string name="action_settings">Параметри</string>
+ <string name="action_save">Зберегти</string>
+ <string name="action_fromat">Увімкнути форматування</string>
+ <string name="action_search">Пошук</string>
+ <string name="action_UNO_commands">Надіслати кмд UNO</string>
+ <string name="message_saved">Збережено</string>
+ <string name="message_saving">Запис документа…</string>
+ <string name="password">Пароль</string>
+ <string name="action_undo">Відміна</string>
+ <string name="action_redo">Повтор</string>
+ <string name="save_alert_dialog_title">Зберегти документ перед закриттям\?</string>
+ <string name="save_document">Зберегти</string>
+ <string name="action_cancel">Відмовитись</string>
+ <string name="no_save_document">НІ</string>
+ <string name="action_presentation">Слайд-шоу</string>
+ <string name="action_add_slide">Додати слайд</string>
+ <string name="slideshow_action_back">Назад</string>
+ <string name="calc_delete">Вилучити</string>
+ <string name="calc_hide">Приховати</string>
+ <string name="calc_show">Показати</string>
+ <string name="calc_optimal_length">Оптимальна довжина</string>
+ <string name="calc_adjust_length">Припасувати довжину</string>
+ <string name="calc_adjust_height">Припасувати висоту</string>
+ <string name="calc_adjust_width">Припасувати ширину</string>
+ <string name="calc_optimal_width">Оптимальна ширина</string>
+ <string name="calc_optimal_length_confirm">ОК</string>
+ <string name="action_add_worksheet">Додати робочий аркуш</string>
+ <string name="action_pwd_dialog_OK">ОК</string>
+ <string name="action_pwd_dialog_cancel">Відмовитись</string>
+ <string name="action_pwd_dialog_title">Введіть пароль</string>
+ <string name="take_photo">Зробити фото</string>
+ <string name="select_photo">Обрати фото</string>
+ <string name="select_photo_title">Обрати зображення</string>
+ <string name="no_camera_found">Камера не знайдена</string>
+ <string name="compress_photo_smallest_size">Найменший розмір</string>
+ <string name="compress_photo_medium_size">Середній розмір</string>
+ <string name="compress_photo_max_quality">Макс. якість</string>
+ <string name="compress_photo_no_compress">Не стискати</string>
+ <string name="compress_photo_title">Бажаєте стиснути фото\?</string>
+ <string name="action_copy">Копіювати</string>
+ <string name="action_cut">Вирізати</string>
+ <string name="action_text_copied">Текст скопійовано до буфера</string>
+ <string name="insert_table">Вставити таблицю</string>
+ <string name="select_delete_options">Оберіть параметри видалення:</string>
+ <string name="action_rename_worksheet">Перейменувати аркуш</string>
+ <string name="action_delete_worksheet">Вилучити аркуш</string>
+ <string name="action_delete_slide">Вилучити слайд</string>
+ <string name="part_name_changed">Частину назви змінено.</string>
+ <string name="part_deleted">Частину видалено.</string>
+ <string name="UNO_commands_string_hint">Команда UNO</string>
+ <string name="UNO_commands_string_type_hint">Тип</string>
+ <string name="UNO_commands_string_value_hint">Значення</string>
+ <string name="UNO_commands_string_parent_value_hint">Значення батьківського елемента</string>
+ <string name="action_exportToPDF">Експортувати в PDF</string>
+ <string name="tabhost_paragraph">Абзац</string>
+ <string name="tabhost_insert">Вставити</string>
+ <string name="tabhost_style">Стиль</string>
+ <string name="alert_ok">ОК</string>
+ <string name="alert_cancel">Відміна</string>
+ <string name="current_uno_command">Поточна команда UNO</string>
+ <string name="display_language">Мова на екрані</string>
+ <string name="pdf_export_finished">Експорт до PDF завершено</string>
+ <string name="unable_to_export_pdf">Неможливо експортувати в PDF</string>
+ <string name="unable_to_save">Неможливо зберегти файл</string>
+ <string name="error">Помилка</string>
+ <string name="enter_part_name">Введіть частину назви</string>
+ <string name="page">Сторінка</string>
+ <string name="sheet">Аркуш</string>
+ <string name="slide">Слайд</string>
+ <string name="part">Частина</string>
+ <string name="highlight_color">Колір виділення</string>
+ <string name="font_color">Колір шрифта</string>
+ <string name="action_rename_slide">Перейменувати слайд</string>
+ <string name="automatic">Автоматично</string>
+ <string name="app_version">Версія: %1$s&lt;br&gt;ID збірки: &lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_name_settings">Налаштування Оглядача LibreOffice</string>
+ <string name="new_textdocument">Новий текстовий документ</string>
+ <string name="title_recents">Попередні файли</string>
+ <string name="about_privacy_policy">Політика приватності</string>
+ <string name="action_save_as">Зберегти як…</string>
+ <string name="calc_optimal_height">Оптимальна висота</string>
+ <string name="name_already_used">Така назва вже використовується.</string>
+ <string name="select_insert_options">Оберіть параметри вставки:</string>
+ <string name="pref_experimental_editing">Експериментальний режим</string>
+ <string name="calc_optimal_length_default_text">Введіть додаткову довжину у 100th/мм</string>
+ <string name="action_paste">Вставити</string>
+ <string name="pref_experimental_editing_summary">Активуйте експериментальний режим редагування. Використовуйте на власний ризик.</string>
+ <string name="action_keyboard">Показати клавіатуру</string>
+ <string name="message_saving_failed">Запис документа перервано.</string>
+ <string name="calc_insert_before">Вставити</string>
+ <string name="calc_alert_double_click_optimal_length">Підказка: подвійний тиць на заголовку встановлює оптимальну ширину/висоту.</string>
+ <string name="action_back">Назад</string>
+ <string name="action_print">Друк</string>
+ <string name="tabhost_character">Символ</string>
+ <string name="display_language_summary">Встановити типову мову</string>
+ <string name="bmp_null">Bmp має нульове значення!</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values-zh-rTW/strings.xml b/android/source/res/values-zh-rTW/strings.xml
new file mode 100644
index 000000000000..60de641f125e
--- /dev/null
+++ b/android/source/res/values-zh-rTW/strings.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">LibreOffice 檢視器</string>
+ <string name="app_name_settings">LibreOffice 檢視器設定</string>
+ <string name="app_version">版本:%1$s&lt;br&gt;建置 ID:&lt;a href=https://hub.libreoffice.org/git-core/%2$s&gt;%2$s&lt;/a&gt;</string>
+ <string name="app_description">LibreOffice 檢視器是以 LibreOffice 為基礎開發的文件檢視器。</string>
+ <string name="app_credits">https://www.libreoffice.org</string>
+ <string name="app_vendor">此版本由 $VENDOR 提供。</string>
+ <string name="readonly_file">此檔案唯讀。</string>
+ <string name="about_license">顯示授權條款</string>
+ <string name="action_keyboard">顯示鍵盤</string>
+ <string name="action_save">儲存</string>
+ <string name="action_fromat">啟用格式</string>
+ <string name="action_search">搜尋</string>
+ <string name="action_UNO_commands">傳送 UNO 命令</string>
+ <string name="message_saved">儲存完成</string>
+ <string name="message_saving">正在儲存文件……</string>
+ <string name="message_saving_failed">儲存文件失敗。</string>
+ <string name="no_camera_found">找不到相機</string>
+ <string name="compress_photo_smallest_size">最小大小</string>
+ <string name="select_photo">選取照片</string>
+ <string name="select_photo_title">選取圖片</string>
+ <string name="compress_photo_medium_size">中等大小</string>
+ <string name="compress_photo_max_quality">最高品質</string>
+ <string name="compress_photo_no_compress">不要壓縮</string>
+ <string name="action_rename_worksheet">重新命名工作表</string>
+ <string name="select_delete_options">選取刪除選項:</string>
+ <string name="action_delete_worksheet">刪除工作表</string>
+ <string name="action_delete_slide">刪除投影片</string>
+ <string name="name_already_used">指定名稱已被使用。</string>
+ <string name="part_name_changed">部份名稱已變更。</string>
+ <string name="part_deleted">部份已刪除。</string>
+ <string name="current_uno_command">目前 UNO 命令</string>
+ <string name="error">錯誤</string>
+ <string name="alert_cancel">取消</string>
+ <string name="action_save_as">另存為……</string>
+ <string name="about_privacy_policy">隱私權政策</string>
+ <string name="create_file">建立新檔案</string>
+ <string name="new_textdocument">新文字文件</string>
+ <string name="new_presentation">新簡報</string>
+ <string name="new_spreadsheet">新試算表</string>
+ <string name="new_drawing">新繪圖</string>
+ <string name="default_document_name">無題</string>
+ <string name="search_find_next">尋找下一個</string>
+ <string name="search_find_previous">尋找上一個</string>
+ <string name="file_icon_desc">檔案圖示</string>
+ <string name="title_recents">最近檔案</string>
+ <string name="title_browser">所有檔案</string>
+ <string name="pref_category_general">一般</string>
+ <string name="pref_experimental_editing">實驗性模式</string>
+ <string name="pref_developer_mode">開發者模式</string>
+ <string name="pref_developer_mode_summary">啟用開發者模式,您可以在應用程式內傳送 UNO 命令。使用風險自負。</string>
+ <string name="action_about">關於</string>
+ <string name="action_parts">部份</string>
+ <string name="action_settings">設定</string>
+ <string name="password">密碼</string>
+ <string name="action_undo">取消動作</string>
+ <string name="action_redo">再次動作</string>
+ <string name="save_alert_dialog_title">關閉前儲存文件?</string>
+ <string name="save_document">儲存</string>
+ <string name="action_cancel">取消</string>
+ <string name="action_add_slide">新增投影片</string>
+ <string name="slideshow_action_back">返回</string>
+ <string name="calc_insert_before">插入</string>
+ <string name="calc_delete">刪除</string>
+ <string name="calc_hide">隱藏</string>
+ <string name="calc_show">顯示</string>
+ <string name="calc_adjust_height">調整高度</string>
+ <string name="calc_adjust_width">調整寬度</string>
+ <string name="calc_adjust_length">調整長度</string>
+ <string name="calc_optimal_length">最適長度</string>
+ <string name="calc_optimal_height">最適高度</string>
+ <string name="calc_optimal_width">最適寬度</string>
+ <string name="calc_optimal_length_confirm">確定</string>
+ <string name="calc_alert_double_click_optimal_length">提示:輕點標題列兩次可以設定最適寬度/高度。</string>
+ <string name="action_add_worksheet">新增工作表</string>
+ <string name="action_pwd_dialog_OK">確定</string>
+ <string name="action_pwd_dialog_cancel">取消</string>
+ <string name="action_pwd_dialog_title">請輸入密碼</string>
+ <string name="take_photo">拍照</string>
+ <string name="compress_photo_title">您想要壓縮照片嗎?</string>
+ <string name="action_copy">複製</string>
+ <string name="action_paste">貼上</string>
+ <string name="action_cut">剪下</string>
+ <string name="action_back">返回</string>
+ <string name="action_text_copied">文字已複製到剪貼簿</string>
+ <string name="insert_table">插入表格</string>
+ <string name="select_insert_options">選取插入選項:</string>
+ <string name="UNO_commands_string_hint">UNO 命令</string>
+ <string name="UNO_commands_string_type_hint">類型</string>
+ <string name="UNO_commands_string_value_hint">值</string>
+ <string name="UNO_commands_string_parent_value_hint">上層值</string>
+ <string name="action_exportToPDF">匯出為 PDF</string>
+ <string name="action_print">列印</string>
+ <string name="tabhost_character">字元</string>
+ <string name="tabhost_paragraph">段落</string>
+ <string name="tabhost_insert">插入</string>
+ <string name="tabhost_style">樣式</string>
+ <string name="alert_ok">確定</string>
+ <string name="display_language">顯示語言</string>
+ <string name="pdf_export_finished">PDF 匯出結束</string>
+ <string name="unable_to_export_pdf">無法匯出為 PDF</string>
+ <string name="unable_to_save">無法儲存檔案</string>
+ <string name="enter_part_name">輸入部份名稱</string>
+ <string name="bmp_null">Bmp 為空!</string>
+ <string name="page">頁面</string>
+ <string name="sheet">工作表</string>
+ <string name="slide">投影片</string>
+ <string name="part">部份</string>
+ <string name="highlight_color">標明色彩</string>
+ <string name="font_color">字型色彩</string>
+ <string name="action_rename_slide">重新命名投影片</string>
+ <string name="automatic">自動</string>
+ <string name="select_file_to_open">選取要開啟的檔案</string>
+ <string name="about_notice">顯示注意事項</string>
+ <string name="no_save_document">否</string>
+ <string name="display_language_summary">設定預設顯示語言</string>
+ <string name="pref_experimental_editing_summary">啟用實驗性編輯模式。使用風險自負。</string>
+ <string name="calc_optimal_length_default_text">輸入額外長度(以 100th/mm 為單位)</string>
+ <string name="action_presentation">投影片放映</string>
+</resources> \ No newline at end of file
diff --git a/android/source/res/values/arrays.xml b/android/source/res/values/arrays.xml
index edea6443b419..832bca781572 100644
--- a/android/source/res/values/arrays.xml
+++ b/android/source/res/values/arrays.xml
@@ -1,62 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <integer-array name="FilterTypeValues">
- <item >-1</item>
- <item >0</item>
- <item >1</item>
- <item >2</item>
- </integer-array>
- <string-array name="FilterTypeStringValues">
- <item >-1</item>
- <item >0</item>
- <item >1</item>
- <item >2</item>
- <item >3</item>
- </string-array>
<string-array name="SupportedLanguagesValues">
<item>SYSTEM_DEFAULT_LANGUAGE</item>
<item >de</item>
<item >en</item>
<item >tr</item>
</string-array>
- <string-array name="SortModeStringValues">
- <item >0</item>
- <item >1</item>
- <item >2</item>
- <item >3</item>
- <item >4</item>
- <item >5</item>
- </string-array>
- <!-- View Mode names,values -->
- <string-array name="ViewModeNames">
- <item >@string/grid_view</item>
- <item >@string/list_view</item>
- </string-array>
- <string-array name="ViewModeStringValues">
- <item >0</item>
- <item >1</item>
- </string-array>
- <string-array name="FilterTypeNames">
- <item>@string/filter_everything</item>
- <item>@string/filter_documents</item>
- <item>@string/filter_spreadsheets</item>
- <item>@string/filter_presentations</item>
- <item>@string/filter_drawings</item>
- </string-array>
<string-array name="SupportedLanguages">
<item>(System Default)</item>
<item>Deutsch</item>
<item>English</item>
<item>Turkçe</item>
</string-array>
- <string-array name="SortModeNames">
- <item >@string/sort_az</item>
- <item >@string/sort_za</item>
- <item >@string/sort_oldest</item>
- <item >@string/sort_newest</item>
- <item >@string/sort_largest</item>
- <item >@string/sort_smallest</item>
- </string-array>
-
-
</resources>
diff --git a/android/source/res/values/colors.xml b/android/source/res/values/colors.xml
index 3defb9a3ea83..4642a2b8f1c1 100644
--- a/android/source/res/values/colors.xml
+++ b/android/source/res/values/colors.xml
@@ -4,6 +4,11 @@
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<resources>
+
+ <!-- "?attr/colorBackgroundFloating" could be used directly instead for API level >= 23,
+ but current minimum API level is lower. Overridden for dark theme in values-night/color.xml. -->
+ <color name="background_floating">@color/background_floating_material_light</color>
+
<color name="background_light">#FAFAFA</color> <!--Material Grey 50-->
<color name="background_normal">#F5F5F5</color> <!--Material Grey 100-->
<color name="background_private">#FF292C29</color>
@@ -93,7 +98,6 @@
<color name="panel_grid_item_image_background">#D1D9E1</color>
<color name="toolbar_foreground">#3e3e3e</color>
- <color name="toolbar_background">#ffffff</color>
<color name="handle_color">#26a69a</color>
diff --git a/android/source/res/values/dimens.xml b/android/source/res/values/dimens.xml
index ca91a2f30a1f..8753fad07101 100644
--- a/android/source/res/values/dimens.xml
+++ b/android/source/res/values/dimens.xml
@@ -11,7 +11,6 @@
<dimen name="toolbar_height">256dp</dimen>
<dimen name="calc_header_width">48dp</dimen>
<dimen name="calc_header_height">24dp</dimen>
- <dimen name="calc_toolbar_height">40dp</dimen>
<dimen name="calc_address_bar_width">96dp</dimen>
<dimen name="new_doc_fab_tweak_top">-11dp</dimen>
<dimen name="new_doc_fab_tweak_bottom">-7dp</dimen>
diff --git a/android/source/res/values/integers.xml b/android/source/res/values/integers.xml
deleted file mode 100644
index aeb71c3997d1..000000000000
--- a/android/source/res/values/integers.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
-
- <integer name="grid_view_integer">0</integer>
-
-</resources> \ No newline at end of file
diff --git a/android/source/res/values/strings.xml b/android/source/res/values/strings.xml
index 3669d0a2ed90..3766db146098 100644
--- a/android/source/res/values/strings.xml
+++ b/android/source/res/values/strings.xml
@@ -4,95 +4,44 @@
<string name="app_name">LibreOffice Viewer</string>
<string name="app_name_settings">LibreOffice Viewer Settings</string>
- <string name="app_about_name"><b>LibreOffice Viewer \'Beta\'</b></string>
- <string name="app_version">Version: %1$s\nBuild ID: %2$s</string>
+ <string name="app_version">Version: %1$s&lt;br&gt;Build ID: &lt;a href=&quot;https://hub.libreoffice.org/git-core/%2$s&quot;&gt;%2$s&lt;/a&gt;</string>
<string name="app_description">LibreOffice Viewer is a document viewer based on LibreOffice.</string>
<string name="app_credits">https://www.libreoffice.org</string>
<string name="app_vendor">This release was supplied by $VENDOR.</string>
- <string name="temp_file_saving_disabled">This file is read-only, saving is disabled.</string>
+ <string name="readonly_file">This file is read-only.</string>
<string name="about_license">Show License</string>
<string name="about_notice">Show Notice</string>
- <string name="about_moreinfo">More Info</string>
- <string name="back_again_to_quit">Press back again to quit</string>
+ <string name="about_privacy_policy">Privacy Policy</string>
+ <string name="create_file">Create New File</string>
<string name="new_textdocument">New Text Document</string>
<string name="new_presentation">New Presentation</string>
<string name="new_spreadsheet">New Spreadsheet</string>
<string name="new_drawing">New Drawing</string>
<string name="default_document_name">untitled</string>
- <string name="browser_app_name">LibreOffice Browser</string>
- <string name="menu_search">Search</string>
- <string name="list_view">List</string>
- <string name="grid_view">Grid</string>
- <string name="filter">Filter by</string>
- <string name="search_not_found">Keyword not found</string>
- <string name="sort">Sort by</string>
- <string name="sort_smallest">Smallest first</string>
- <string name="sort_largest">Largest first</string>
- <string name="sort_az">A-Z</string>
- <string name="sort_za">Z-A</string>
- <string name="sort_oldest">Oldest first</string>
- <string name="sort_newest">Newest first</string>
- <string name="menu_sort_size">Sort By Size</string>
- <string name="menu_sort_az">Sort A-Z</string>
- <string name="menu_sort_modified">Sort by Date</string>
- <string name="menu_preferences">Preferences</string>
+ <string name="select_file_to_open">Select file to open</string>
+
+ <string name="search_find_next">Find Next</string>
+ <string name="search_find_previous">Find Previous</string>
<string name="file_icon_desc">fileicon</string>
<string name="title_recents">Recent files</string>
<string name="title_browser">All files</string>
- <!-- Pref keys as resources ; Not currently used -->
- <string name="EXPLORER_VIEW_TYPE_KEY">EXPLORER_VIEW_TYPE</string>
- <string name="CURRENT_DIRECTORY_KEY">CURRENT_DIRECTORY</string>
- <string name="pref_category_explorer">File Explorer Settings</string>
<string name="pref_category_general">General</string>
<string name="pref_experimental_editing">Experimental Mode</string>
<string name="pref_experimental_editing_summary">Enable the experimental editing mode. Use at your own risk.</string>
- <string name="pref_show_hidden_files">Hidden Files/Folders</string>
- <string name="pref_show_hidden_files_summary">Enable to show hidden files/folders</string>
<string name="pref_developer_mode">Developer Mode</string>
<string name="pref_developer_mode_summary">Enable developer mode where you can send UNO commands within app. Use at your own risk.</string>
<string name="action_about">About</string>
<string name="action_parts">Parts</string>
<string name="action_settings">Settings</string>
- <string name="open">Open</string>
- <string name="share">Share</string>
- <string name="share_via">Share via</string>
-
- <!-- Document browser filters -->
- <string name="filter_everything">Everything</string>
- <string name="filter_documents">Documents</string>
- <string name="filter_spreadsheets">Spreadsheets</string>
- <string name="filter_presentations">Presentations</string>
- <string name="filter_drawings">Drawings</string>
-
- <!-- Document provider names -->
- <string name="document_locations">Document locations</string>
- <string name="close_document_locations">Close document locations</string>
- <string name="local_documents">Documents directory</string>
- <string name="local_file_system">Local file system</string>
- <string name="external_sd_file_system">External SD</string>
- <string name="otg_file_system">OTG device (experimental)</string>
- <string name="owncloud">Remote server</string>
- <string name="usb_connected_configure">USB connected, configure your device.</string>
-
- <string name="owncloud_wrong_connection">Cannot connect to ownCloud server. Check your configuration.</string>
- <string name="owncloud_unauthorized">Cannot log into ownCloud server. Check your configuration.</string>
- <string name="owncloud_unspecified_error">Unspecified error connecting to ownCloud server. Check your configuration and/or try later.</string>
-
- <string name="ext_document_provider_error">Invalid root file. Check your sd card configuration.</string>
- <string name="legacy_extsd_missing_error">Invalid root file. Check your external sd card and/or configuration.</string>
- <string name="otg_missing_error">Invalid root file. Check your OTG device and/or configuration.</string>
<!-- Edit action names -->
- <string name="action_bold">Bold</string>
- <string name="action_underline">Underline</string>
- <string name="action_italic">Italic</string>
- <string name="action_strikeout">Strike Out</string>
<string name="action_keyboard">Show keyboard</string>
<string name="action_save">Save</string>
+ <string name="action_save_as">Save As…</string>
<string name="action_fromat">Enable Format</string>
<string name="action_search">Search</string>
<string name="action_UNO_commands">Send UNO Cmd</string>
@@ -100,48 +49,21 @@
<!-- Feedback messages -->
<string name="message_saved">Save complete</string>
<string name="message_saving">Saving the document…</string>
- <string name="message_save_incomplete">Save incomplete. Were there any changes?</string>
- <string name="create_new_file_success">"Created new file - "</string>
- <string name="create_new_file_error">Unable to create new file, please check entered file name.</string>
-
- <!-- Document provider settings -->
- <string name="storage_provider_settings">Storage provider settings</string>
- <string name="owncloud_settings">ownCloud settings</string>
- <string name="physical_storage_settings">Physical storage settings</string>
- <string name="external_sd_path">External SD path</string>
- <string name="otg_device_path">OTG device path</string>
- <string name="otg_warning">Experimental Feature: Use only if OTG device is writable.</string>
- <string name="server_url">Server URL</string>
- <string name="server_url_and_port">URL and port of the ownCloud server.</string>
- <string name="user_name">User name</string>
+ <string name="message_saving_failed">Saving the document failed.</string>
+
<string name="password">Password</string>
<string name="action_undo">Undo</string>
<string name="action_redo">Redo</string>
- <!-- Directory browser strings -->
- <string name="up_description">To parent directory</string>
- <string name="confirm_label">Confirm</string>
- <string name="cancel_label">Cancel</string>
- <string name="search_label">Go</string>
- <string name="directory_browser_label">Choose Directory</string>
- <string name="bad_directory">Invalid directory path</string>
- <string name="current_dir">Current Directory: %1$s</string>
-
<!-- Save Alert dialog strings -->
<string name="save_alert_dialog_title">Save the document before closing?</string>
<string name="save_document">SAVE</string>
<string name="action_cancel">Cancel</string>
<string name="no_save_document">NO</string>
- <!-- Create New Document Dialog Strings -->
- <string name="create_new_document_title">Enter file name</string>
- <string name="action_create">CREATE</string>
-
<!-- Presentation Mode Strings -->
<string name="action_presentation">Slide show</string>
<string name="action_add_slide">Add Slide</string>
- <string name="alert_copy_svg_slide_show_to_clipboard">Your Android device doesn\'t support in-app svg slideshow. We copied the slideshow link to clipboard. Please press home button, open a modern web browser, paste in the address bar, and go.</string>
- <string name="alert_copy_svg_slide_show_to_clipboard_dismiss">OK</string>
<string name="slideshow_action_back">Back</string>
<!-- Calc Header Menu Strings -->
@@ -217,23 +139,15 @@
<string name="tabhost_style">Style</string>
<string name="alert_ok">OK</string>
<string name="alert_cancel">Cancel</string>
- <string name="unable_to_go_further">Unable to go further.</string>
<string name="current_uno_command">Current UNO command</string>
- <string name="pref_sort_summary">Select how to order files: A-Z, by size or by date.</string>
- <string name="pref_viewmode_summary">View files as a grid or in a list.</string>
- <string name="pref_file_explorer_title">File explorer layout</string>
- <string name="pref_sort_title">File Order</string>
- <string name="pref_filter_title">Default File Filter</string>
- <string name="pref_filter_summary">Set which file filter should be used by default.</string>
<string name="display_language">Display Language</string>
<string name="display_language_summary">Set the default display language</string>
+ <string name="pdf_export_finished">PDF export finished</string>
<string name="unable_to_export_pdf">Unable to export to pdf</string>
- <string name="pdf_exported_at">Exported to PDF at</string>
- <string name="printing_not_supported">Your device does not support printing</string>
+ <string name="unable_to_save">Unable to save file</string>
<string name="error">Error</string>
<string name="enter_part_name">Enter a part name</string>
<string name="bmp_null">Bmp is null!</string>
- <string name="directory_not_saved">Directory not saved.</string>
<string name="page">Page</string>
<string name="sheet">Sheet</string>
<string name="slide">Slide</string>
@@ -241,4 +155,5 @@
<string name="highlight_color">Highlight Color</string>
<string name="font_color">Font Color</string>
<string name="action_rename_slide">Rename Slide</string>
+ <string name="automatic">Automatic</string>
</resources>
diff --git a/android/source/res/values/themes.xml b/android/source/res/values/themes.xml
index 8576f9c221ec..bf815b5c659f 100644
--- a/android/source/res/values/themes.xml
+++ b/android/source/res/values/themes.xml
@@ -2,17 +2,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="LibreOfficeTheme" parent="LibreOfficeTheme.Base"/>
- <style name="LibreOfficeTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
+ <style name="LibreOfficeTheme.Base" parent="Theme.AppCompat.DayNight.NoActionBar">
</style>
<style name="ListItemText">
<item name="android:gravity">center_vertical</item>
- <item name="android:textColor">@android:color/black</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:textSize">14sp</item>
</style>
- <style name="LibreOfficeTheme.Toolbar" parent="Theme.AppCompat.Light.NoActionBar">
- <item name="colorPrimary">@color/toolbar_background</item>
+ <style name="LibreOfficeTheme.Toolbar" parent="Theme.AppCompat.DayNight.NoActionBar">
</style>
<style name="LibreOfficeTheme.NavigationView">
diff --git a/android/source/res/xml/documentprovider_preferences.xml b/android/source/res/xml/documentprovider_preferences.xml
deleted file mode 100644
index bb5f087ddf71..000000000000
--- a/android/source/res/xml/documentprovider_preferences.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- This file is part of the LibreOffice project.
- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/.
- -->
-<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
- <PreferenceCategory
- android:title="@string/owncloud_settings"
- android:key="pref_key_owncloud_settings">
- <EditTextPreference
- android:key="pref_server_url"
- android:title="@string/server_url"
- android:summary="@string/server_url_and_port"
- android:hint="https://server:port/" />
- <EditTextPreference
- android:key="pref_user_name"
- android:title="@string/user_name" />
- <EditTextPreference
- android:key="pref_password"
- android:title="@string/password"
- android:password="true" />
- </PreferenceCategory>
- <PreferenceCategory
- android:title="@string/physical_storage_settings">
- <PreferenceScreen
- android:title="@string/external_sd_path"
- android:key="pref_extsd_path_uri">
- </PreferenceScreen>
- <PreferenceScreen
- android:title="@string/otg_device_path"
- android:key="pref_otg_path_uri"
- android:summary="@string/otg_warning">
- </PreferenceScreen>
- </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/android/source/res/xml/libreoffice_preferences.xml b/android/source/res/xml/libreoffice_preferences.xml
index d418dd559f86..052efacb2e3e 100644
--- a/android/source/res/xml/libreoffice_preferences.xml
+++ b/android/source/res/xml/libreoffice_preferences.xml
@@ -1,37 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
- android:title="@string/pref_category_explorer"
- android:key="PREF_CATEGORY_EXPLORER">
- <ListPreference
- android:title="@string/pref_filter_title"
- android:summary="@string/pref_filter_summary"
- android:entries="@array/FilterTypeNames"
- android:entryValues="@array/FilterTypeStringValues"
- android:defaultValue="-1"
- android:key="FILTER_MODE"/>
- <ListPreference
- android:summary="@string/pref_sort_summary"
- android:key="SORT_MODE"
- android:title="@string/pref_sort_title"
- android:entries="@array/SortModeNames"
- android:defaultValue="0"
- android:entryValues="@array/SortModeStringValues"/>
- <ListPreference
- android:entries="@array/ViewModeNames"
- android:entryValues="@array/ViewModeStringValues"
- android:defaultValue="@integer/grid_view_integer"
- android:title="@string/pref_file_explorer_title"
- android:key="EXPLORER_VIEW_TYPE"
- android:summary="@string/pref_viewmode_summary" />
-
- <CheckBoxPreference
- android:title="@string/pref_show_hidden_files"
- android:key="ENABLE_SHOW_HIDDEN_FILES"
- android:summary="@string/pref_show_hidden_files_summary"
- android:defaultValue="false" />
- </PreferenceCategory>
- <PreferenceCategory
android:title="@string/pref_category_general"
android:key="PREF_CATEGORY_GENERAL">
diff --git a/android/source/src/java/org/libreoffice/AboutDialogFragment.java b/android/source/src/java/org/libreoffice/AboutDialogFragment.java
index 6c944bae7ef1..0d9fc45856ef 100644
--- a/android/source/src/java/org/libreoffice/AboutDialogFragment.java
+++ b/android/source/src/java/org/libreoffice/AboutDialogFragment.java
@@ -18,21 +18,16 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.fragment.app.DialogFragment;
import android.text.Html;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.View;
import android.widget.TextView;
-import java.io.File;
-
public class AboutDialogFragment extends DialogFragment {
- private static final String DEFAULT_DOC_PATH = "/assets/example.odt";
-
-
@NonNull @Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
@@ -45,66 +40,60 @@ public class AboutDialogFragment extends DialogFragment {
int defaultColor = textView.getTextColors().getDefaultColor();
textView.setTextColor(defaultColor);
- // Take care of placeholders in the version and vendor text views.
- TextView versionView = messageView.findViewById(R.id.about_version);
- TextView vendorView = messageView.findViewById(R.id.about_vendor);
+ // Take care of placeholders and set text in version and vendor text views.
try
{
String versionName = getActivity().getPackageManager()
.getPackageInfo(getActivity().getPackageName(), 0).versionName;
- String[] tokens = versionName.split("/");
- if (tokens.length == 3)
- {
- String version = String.format(versionView.getText().toString().replace("\n", "<br/>"),
- tokens[0], "<a href=\"https://hub.libreoffice.org/git-core/" + tokens[1] + "\">" + tokens[1] + "</a>");
- @SuppressWarnings("deprecation") // since 24 with additional option parameter
- Spanned versionString = Html.fromHtml(version);
- versionView.setText(versionString);
- versionView.setMovementMethod(LinkMovementMethod.getInstance());
- String vendor = vendorView.getText().toString();
- vendor = vendor.replace("$VENDOR", tokens[2]);
- vendorView.setText(vendor);
- }
- else
- throw new PackageManager.NameNotFoundException();
+ String version = String.format(getString(R.string.app_version), versionName, BuildConfig.BUILD_ID_SHORT);
+ @SuppressWarnings("deprecation") // since 24 with additional option parameter
+ Spanned versionString = Html.fromHtml(version);
+ TextView versionView = messageView.findViewById(R.id.about_version);
+ versionView.setText(versionString);
+ versionView.setMovementMethod(LinkMovementMethod.getInstance());
+ TextView vendorView = messageView.findViewById(R.id.about_vendor);
+ String vendor = getString(R.string.app_vendor).replace("$VENDOR", BuildConfig.VENDOR);
+ vendorView.setText(vendor);
}
catch (PackageManager.NameNotFoundException e)
{
- versionView.setText("");
- vendorView.setText("");
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
- builder .setIcon(R.drawable.lo_icon)
+ builder .setIcon(R.mipmap.ic_launcher)
.setTitle(R.string.app_name)
.setView(messageView)
.setNegativeButton(R.string.about_license, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- loadFromAbout("/assets/license.txt");
+ loadFromAbout(R.raw.license);
dialog.dismiss();
}
})
.setPositiveButton(R.string.about_notice, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
- loadFromAbout("/assets/notice.txt");
- dialog.dismiss();
- }
- })
- .setNeutralButton(R.string.about_moreinfo, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int id) {
- loadFromAbout(DEFAULT_DOC_PATH);
+ loadFromAbout(R.raw.notice);
dialog.dismiss();
}
});
+ // when privacy policy URL is set (via '--with-privacy-policy-url=<url>' autogen option),
+ // add button to open that URL
+ final String privacyUrl = BuildConfig.PRIVACY_POLICY_URL;
+ if (!privacyUrl.isEmpty() && privacyUrl != "undefined") {
+ builder.setNeutralButton(R.string.about_privacy_policy, (DialogInterface dialog, int id) -> {
+ Intent openPrivacyUrlIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(privacyUrl));
+ startActivity(openPrivacyUrlIntent);
+ dialog.dismiss();
+ });
+ }
+
return builder.create();
}
- private void loadFromAbout(String input) {
- Intent i = new Intent(Intent.ACTION_VIEW, Uri.fromFile(new File(input)));
+ private void loadFromAbout(int resourceId) {
+ Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse("android.resource://" + BuildConfig.APPLICATION_ID + "/" + resourceId));
String packageName = getActivity().getApplicationContext().getPackageName();
ComponentName componentName = new ComponentName(packageName, LibreOfficeMainActivity.class.getName());
i.setComponent(componentName);
diff --git a/android/source/src/java/org/libreoffice/ColorPaletteAdapter.java b/android/source/src/java/org/libreoffice/ColorPaletteAdapter.java
index 6ec6aa138f66..16d8a977864f 100644
--- a/android/source/src/java/org/libreoffice/ColorPaletteAdapter.java
+++ b/android/source/src/java/org/libreoffice/ColorPaletteAdapter.java
@@ -1,7 +1,7 @@
package org.libreoffice;
import android.content.Context;
-import android.support.v7.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -12,12 +12,12 @@ import android.widget.ImageButton;
public class ColorPaletteAdapter extends RecyclerView.Adapter<ColorPaletteAdapter.ColorPaletteViewHolder> {
- int[][] color_palette;
- Context mContext;
- int upperSelectedBox = -1;
- int selectedBox = 0;
- boolean animate;
- ColorPaletteListener colorPaletteListener;
+ private int[][] color_palette;
+ private final Context mContext;
+ private int upperSelectedBox = -1;
+ private int selectedBox = 0;
+ private boolean animate;
+ private final ColorPaletteListener colorPaletteListener;
public ColorPaletteAdapter(Context mContext, ColorPaletteListener colorPaletteListener) {
this.mContext = mContext;
@@ -36,6 +36,10 @@ public class ColorPaletteAdapter extends RecyclerView.Adapter<ColorPaletteAdapte
return selectedBox;
}
+ public int getUpperSelectedBox() {
+ return upperSelectedBox;
+ }
+
@Override
public void onBindViewHolder(final ColorPaletteViewHolder holder, int position) {
@@ -128,4 +132,4 @@ public class ColorPaletteAdapter extends RecyclerView.Adapter<ColorPaletteAdapte
}
-} \ No newline at end of file
+}
diff --git a/android/source/src/java/org/libreoffice/ColorPickerAdapter.java b/android/source/src/java/org/libreoffice/ColorPickerAdapter.java
index c93d5a01bbb4..a17dd264fb99 100644
--- a/android/source/src/java/org/libreoffice/ColorPickerAdapter.java
+++ b/android/source/src/java/org/libreoffice/ColorPickerAdapter.java
@@ -3,7 +3,7 @@ package org.libreoffice;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
-import android.support.v7.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -12,12 +12,11 @@ import android.widget.ImageButton;
public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.ColorPickerViewHolder> {
- Context mContext;
- ColorPaletteAdapter colorPaletteAdapter;
- ColorPaletteListener colorPaletteListener;
- int[] colorList;
- int[][] colorPalette = new int[11][8];
- int selectedBox = 0;
+ private final Context mContext;
+ private final ColorPaletteAdapter colorPaletteAdapter;
+ private final ColorPaletteListener colorPaletteListener;
+ private final int[] colorList;
+ private final int[][] colorPalette = new int[11][8];
public ColorPickerAdapter(Context mContext, final ColorPaletteAdapter colorPaletteAdapter, ColorPaletteListener colorPaletteListener) {
this.mContext = mContext;
@@ -41,10 +40,11 @@ public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.
public void onBindViewHolder(final ColorPickerViewHolder holder, int position) {
holder.colorBox.setBackgroundColor(colorList[position]);
- if (selectedBox != position)
- holder.colorBox.setImageDrawable(null);
- else {
+ if (colorPaletteAdapter.getUpperSelectedBox() == position
+ && colorPaletteAdapter.getSelectedBox() >= 0) {
holder.colorBox.setImageResource(R.drawable.ic_done_white_12dp);
+ } else {
+ holder.colorBox.setImageDrawable(null);
}
holder.colorBox.setOnClickListener(new View.OnClickListener() {
@@ -64,12 +64,20 @@ public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.
private void setPosition(int position) {
- this.selectedBox = position;
selectSubColor(position, position==0?0:3);
colorPaletteListener.applyColor(colorList[position]);
updateAdapter();
}
+ /**
+ * Switches to first palette, but doesn't mark any color as selected.
+ * Use this if no color in the palette matches the actual one.
+ */
+ public void unselectColors() {
+ colorPaletteAdapter.changePosition(0, -1);
+ updateAdapter();
+ }
+
private void selectSubColor(int position1, int position2) {
colorPaletteAdapter.setPosition(position1, position2);
}
@@ -88,7 +96,15 @@ public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.
int red_shade = red;
int green_shade = green;
int blue_shade = blue;
- if (i != 0) {
+ if (i == 0) {
+ colorPalette[0][0] = colorList[i];
+ for (int k = 1; k < 7; k++) {
+ red_tint = (int) (red_tint + (255 - red_tint) * 0.25);
+ green_tint = (int) (green_tint + (255 - green_tint) * 0.25);
+ blue_tint = (int) (blue_tint + (255 - blue_tint) * 0.25);
+ colorPalette[i][k] = (Color.rgb(red_tint, green_tint, blue_tint));
+ }
+ } else {
colorPalette[i][3] = colorList[i];
for (int k = 2; k >= 0; k--) {
red_shade = (int) (red_shade * 0.75);
@@ -102,48 +118,28 @@ public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.
blue_tint = (int) (blue_tint + (255 - blue_tint) * 0.45);
colorPalette[i][k] = (Color.rgb(red_tint, green_tint, blue_tint));
}
- } else {
- colorPalette[0][0] = colorList[i];
- for (int k = 1; k < 7; k++) {
- red_tint = (int) (red_tint + (255 - red_tint) * 0.25);
- green_tint = (int) (green_tint + (255 - green_tint) * 0.25);
- blue_tint = (int) (blue_tint + (255 - blue_tint) * 0.25);
- colorPalette[i][k] = (Color.rgb(red_tint, green_tint, blue_tint));
- }
}
- }
- for (int i = 0; i < 11; i++){
- this.colorPalette[i][7] = (Color.rgb(255, 255, 255)); // last one is always white
+ colorPalette[i][7] = Color.WHITE; // last one is always white
}
colorPaletteAdapter.setColorPalette(colorPalette);
}
public void findSelectedTextColor(int color) {
- /*
- Libreoffice recognizes -1 as Black
- */
- if (color == -1) {
- colorPaletteAdapter.changePosition(0, 0);
- selectedBox = 0;
- updateAdapter();
- return;
- }
- /*
- Find the color if the palette points another color
- */
- if (colorPalette[selectedBox][colorPaletteAdapter.getSelectedBox()] != color) {
- for (int i = 0; i < 11; i++) {
- for (int k = 0; k < 8; k++) {
- if (colorPalette[i][k] == color) {
- colorPaletteAdapter.changePosition(i, k);
- selectedBox = i;
- updateAdapter();
- return;
- }
+ // try to find and highlight the color in the existing palettes
+ for (int i = 0; i < 11; i++) {
+ for (int k = 0; k < 8; k++) {
+ if (colorPalette[i][k] == color) {
+ colorPaletteAdapter.changePosition(i, k);
+ updateAdapter();
+ return;
}
}
}
+
+ // no color in the palettes matched
+ unselectColors();
}
+
private void updateAdapter(){
LOKitShell.getMainHandler().post(new Runnable() {
@Override
@@ -163,4 +159,4 @@ public class ColorPickerAdapter extends RecyclerView.Adapter<ColorPickerAdapter.
this.colorBox = itemView.findViewById(R.id.fontColorBox);
}
}
-} \ No newline at end of file
+}
diff --git a/android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java b/android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java
index a576fc67dcb2..a0ed871a40d2 100644
--- a/android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java
+++ b/android/source/src/java/org/libreoffice/DocumentPartViewListAdapter.java
@@ -19,7 +19,6 @@ import android.widget.TextView;
import java.util.List;
public class DocumentPartViewListAdapter extends ArrayAdapter<DocumentPartView> {
- private static final String LOGTAG = DocumentPartViewListAdapter.class.getSimpleName();
private final Activity activity;
private final ThumbnailCreator thumbnailCollector;
diff --git a/android/source/src/java/org/libreoffice/FontController.java b/android/source/src/java/org/libreoffice/FontController.java
index a00e13e1485c..72f35d8b42d8 100644
--- a/android/source/src/java/org/libreoffice/FontController.java
+++ b/android/source/src/java/org/libreoffice/FontController.java
@@ -2,12 +2,13 @@ package org.libreoffice;
import android.graphics.Color;
import android.graphics.Rect;
-import android.support.design.widget.BottomSheetBehavior;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.RecyclerView;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
@@ -23,12 +24,15 @@ import java.util.Iterator;
public class FontController implements AdapterView.OnItemSelectedListener {
+ /** -1 as value in ".uno:Color" et al. means "automatic color"/no color set. */
+ private static final int COLOR_AUTO = -1;
+
private boolean mFontNameSpinnerSet = false;
private boolean mFontSizeSpinnerSet = false;
private final LibreOfficeMainActivity mActivity;
- private final ArrayList<String> mFontList = new ArrayList<String>();
- private final ArrayList<String> mFontSizes = new ArrayList<String>();
- private final HashMap<String, ArrayList<String>> mAllFontSizes = new HashMap<String, ArrayList<String>>();
+ private final ArrayList<String> mFontList = new ArrayList<>();
+ private final ArrayList<String> mFontSizes = new ArrayList<>();
+ private final HashMap<String, ArrayList<String>> mAllFontSizes = new HashMap<>();
private String mCurrentFontSelected = null;
private String mCurrentFontSizeSelected = null;
@@ -45,29 +49,44 @@ public class FontController implements AdapterView.OnItemSelectedListener {
final ColorPaletteListener colorPaletteListener = new ColorPaletteListener() {
@Override
public void applyColor(int color) {
- sendFontColorChange(color);
+ sendFontColorChange(color, false);
}
@Override
public void updateColorPickerPosition(int color) {
- if (null == colorPickerAdapter) return;
- colorPickerAdapter.findSelectedTextColor(color + 0xFF000000);
- changeFontColorBoxColor(color + 0xFF000000);
+ if (colorPickerAdapter == null) {
+ return;
+ }
+ if (color == COLOR_AUTO) {
+ colorPickerAdapter.unselectColors();
+ changeFontColorBoxColor(Color.TRANSPARENT);
+ return;
+ }
+ final int colorWithAlpha = color | 0xFF000000;
+ colorPickerAdapter.findSelectedTextColor(colorWithAlpha);
+ changeFontColorBoxColor(colorWithAlpha);
}
};
final ColorPaletteListener backColorPaletteListener = new ColorPaletteListener() {
@Override
public void applyColor(int color) {
- sendFontBackColorChange(color);
+ sendFontBackColorChange(color, false);
}
@Override
public void updateColorPickerPosition(int color) {
- if(backColorPickerAdapter != null)
- backColorPickerAdapter.findSelectedTextColor(color + 0xFF000000);
- changeFontBackColorBoxColor(color + 0xFF000000);
-
+ if (backColorPickerAdapter == null) {
+ return;
+ }
+ if (color == COLOR_AUTO) {
+ backColorPickerAdapter.unselectColors();
+ changeFontBackColorBoxColor(Color.TRANSPARENT);
+ return;
+ }
+ final int colorWithAlpha = color | 0xFF000000;
+ backColorPickerAdapter.findSelectedTextColor(colorWithAlpha);
+ changeFontBackColorBoxColor(colorWithAlpha);
}
};
@@ -77,11 +96,7 @@ public class FontController implements AdapterView.OnItemSelectedListener {
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
- if(color == -1){ //Libreoffice recognizes -1 as black
- fontColorPickerButton.setBackgroundColor(Color.BLACK);
- }else{
- fontColorPickerButton.setBackgroundColor(color);
- }
+ fontColorPickerButton.setBackgroundColor(color);
}
});
}
@@ -92,12 +107,7 @@ public class FontController implements AdapterView.OnItemSelectedListener {
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
- if(color == -1){ //Libreoffice recognizes -1 as black
- fontBackColorPickerButton.setBackgroundColor(Color.BLACK);
- }else{
- fontBackColorPickerButton.setBackgroundColor(color);
-
- }
+ fontBackColorPickerButton.setBackgroundColor(color);
}
});
}
@@ -132,12 +142,12 @@ public class FontController implements AdapterView.OnItemSelectedListener {
}
}
- private void sendFontColorChange(int color){
+ private void sendFontColorChange(int color, boolean keepAlpha){
try {
JSONObject json = new JSONObject();
JSONObject valueJson = new JSONObject();
valueJson.put("type", "long");
- valueJson.put("value", 0x00FFFFFF & color);
+ valueJson.put("value", keepAlpha ? color : 0x00FFFFFF & color);
json.put("Color", valueJson);
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Color", json.toString()));
@@ -152,21 +162,18 @@ public class FontController implements AdapterView.OnItemSelectedListener {
* 0x00FFFFFF & color operation removes the alpha which is FF,
* if we don't remove it, the color value becomes negative which is not recognized by LOK
*/
- private void sendFontBackColorChange(int color){
+ private void sendFontBackColorChange(int color, boolean keepAlpha) {
try {
JSONObject json = new JSONObject();
JSONObject valueJson = new JSONObject();
valueJson.put("type", "long");
- valueJson.put("value", 0x00FFFFFF & color);
- if(mActivity.isSpreadsheet()){
+ valueJson.put("value", keepAlpha ? color : 0x00FFFFFF & color);
+ if(mActivity.getTileProvider().isSpreadsheet()){
json.put("BackgroundColor", valueJson);
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:BackgroundColor", json.toString()));
- }else if(mActivity.getTileProvider().isPresentation()){
+ }else {
json.put("CharBackColor", valueJson);
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:CharBackColor", json.toString()));
- }else {
- json.put("BackColor", valueJson);
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:BackColor", json.toString()));
}
changeFontBackColorBoxColor(color);
@@ -213,7 +220,7 @@ public class FontController implements AdapterView.OnItemSelectedListener {
String key = keys.next();
mFontList.add(key);
JSONArray array = jObject2.getJSONArray(key);
- fontSizes = new ArrayList<String>();
+ fontSizes = new ArrayList<>();
for (int i = 0; i < array.length(); i++) {
fontSizes.add(array.getString(i));
}
@@ -237,14 +244,14 @@ public class FontController implements AdapterView.OnItemSelectedListener {
private void setupFontNameSpinner() {
Spinner fontSpinner = mActivity.findViewById(R.id.font_name_spinner);
- ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_spinner_item, mFontList);
+ ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(mActivity, android.R.layout.simple_spinner_item, mFontList);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
fontSpinner.setAdapter(dataAdapter);
}
private void setupFontSizeSpinner() {
Spinner fontSizeSpinner = mActivity.findViewById(R.id.font_size_spinner);
- ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(mActivity, android.R.layout.simple_spinner_item, mFontSizes);
+ ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(mActivity, android.R.layout.simple_spinner_item, mFontSizes);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
fontSizeSpinner.setAdapter(dataAdapter);
}
@@ -306,6 +313,10 @@ public class FontController implements AdapterView.OnItemSelectedListener {
fontColorPicker.setOnClickListener(clickListener);
fontColorPickerButton.setOnClickListener(clickListener);
+ final Button autoColorButton = colorPickerLayout.findViewById(R.id.button_auto_color);
+ autoColorButton.setOnClickListener(view -> {
+ sendFontColorChange(COLOR_AUTO, true);
+ });
}
private void setupBackColorPicker(){
@@ -365,6 +376,10 @@ public class FontController implements AdapterView.OnItemSelectedListener {
fontColorPicker.setOnClickListener(clickListener);
fontColorPickerButton.setOnClickListener(clickListener);
+ final Button autoColorButton = backColorPickerLayout.findViewById(R.id.button_auto_color);
+ autoColorButton.setOnClickListener(view -> {
+ sendFontBackColorChange(COLOR_AUTO, true);
+ });
}
public void selectFont(final String fontName) {
diff --git a/android/source/src/java/org/libreoffice/FormattingController.java b/android/source/src/java/org/libreoffice/FormattingController.java
index a34c4c41ee29..49e81eb69784 100644
--- a/android/source/src/java/org/libreoffice/FormattingController.java
+++ b/android/source/src/java/org/libreoffice/FormattingController.java
@@ -11,8 +11,8 @@ import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
-import android.support.design.widget.Snackbar;
-import android.support.v4.content.FileProvider;
+import com.google.android.material.snackbar.Snackbar;
+import androidx.core.content.FileProvider;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -40,7 +40,7 @@ class FormattingController implements View.OnClickListener {
private static final int SELECT_PHOTO = 2;
private static final int IMAGE_BUFFER_SIZE = 4 * 1024;
- private LibreOfficeMainActivity mContext;
+ private final LibreOfficeMainActivity mContext;
private String mCurrentPhotoPath;
FormattingController(LibreOfficeMainActivity context) {
@@ -48,6 +48,8 @@ class FormattingController implements View.OnClickListener {
mContext.findViewById(R.id.button_insertFormatListBullets).setOnClickListener(this);
mContext.findViewById(R.id.button_insertFormatListNumbering).setOnClickListener(this);
+ mContext.findViewById(R.id.button_increaseIndent).setOnClickListener(this);
+ mContext.findViewById(R.id.button_decreaseIndent).setOnClickListener(this);
mContext.findViewById(R.id.button_bold).setOnClickListener(this);
mContext.findViewById(R.id.button_italic).setOnClickListener(this);
@@ -84,70 +86,51 @@ class FormattingController implements View.OnClickListener {
button.getBackground().setState(new int[]{android.R.attr.state_selected});
}
- switch(button.getId()) {
-
- case R.id.button_insertFormatListBullets:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:DefaultBullet"));
- break;
-
- case R.id.button_insertFormatListNumbering:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:DefaultNumbering"));
- break;
-
- case R.id.button_bold:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Bold"));
- break;
- case R.id.button_italic:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Italic"));
- break;
- case R.id.button_strikethrough:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Strikeout"));
- break;
- case R.id.button_clearformatting:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:ResetAttributes"));
- break;
- case R.id.button_underlined:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:UnderlineDouble"));
- break;
- case R.id.button_align_left:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:LeftPara"));
- break;
- case R.id.button_align_center:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:CenterPara"));
- break;
- case R.id.button_align_right:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:RightPara"));
- break;
- case R.id.button_align_justify:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:JustifyPara"));
- break;
- case R.id.button_insert_line:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Line"));
- break;
- case R.id.button_insert_rect:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Rect"));
- break;
- case R.id.button_font_shrink:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Shrink"));
- break;
- case R.id.button_font_grow:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Grow"));
- break;
- case R.id.button_subscript:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SubScript"));
- break;
- case R.id.button_superscript:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SuperScript"));
- break;
- case R.id.button_insert_picture:
- insertPicture();
- break;
- case R.id.button_insert_table:
- insertTable();
- break;
- case R.id.button_delete_table:
- deleteTable();
- break;
+ final int buttonId = button.getId();
+ if (buttonId == R.id.button_insertFormatListBullets) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:DefaultBullet"));
+ } else if (buttonId == R.id.button_insertFormatListNumbering) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:DefaultNumbering"));
+ } else if (buttonId == R.id.button_increaseIndent) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:IncrementIndent"));
+ } else if (buttonId == R.id.button_decreaseIndent) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:DecrementIndent"));
+ } else if (buttonId == R.id.button_bold) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Bold"));
+ } else if (buttonId == R.id.button_italic) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Italic"));
+ } else if (buttonId == R.id.button_strikethrough) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Strikeout"));
+ } else if (buttonId == R.id.button_clearformatting) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:ResetAttributes"));
+ } else if (buttonId == R.id.button_underlined) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:UnderlineDouble"));
+ } else if (buttonId == R.id.button_align_left) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:LeftPara"));
+ } else if (buttonId == R.id.button_align_center) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:CenterPara"));
+ } else if (buttonId == R.id.button_align_right) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:RightPara"));
+ } else if (buttonId == R.id.button_align_justify) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:JustifyPara"));
+ } else if (buttonId == R.id.button_insert_line) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Line"));
+ } else if (buttonId == R.id.button_insert_rect) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Rect"));
+ } else if (buttonId == R.id.button_font_shrink) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Shrink"));
+ } else if (buttonId == R.id.button_font_grow) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Grow"));
+ } else if (buttonId == R.id.button_subscript) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SubScript"));
+ }else if (buttonId == R.id.button_superscript) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:SuperScript"));
+ } else if (buttonId == R.id.button_insert_picture) {
+ insertPicture();
+ } else if (buttonId == R.id.button_insert_table) {
+ insertTable();
+ } else if (buttonId == R.id.button_delete_table) {
+ deleteTable();
}
}
@@ -243,15 +226,11 @@ class FormattingController implements View.OnClickListener {
public void onClick(View v) {
int rowCount = Integer.parseInt(npRowCount.getText().toString());
int colCount = Integer.parseInt(npColCount.getText().toString());
- switch (v.getId()){
- case R.id.number_picker_rows_positive:
- if(rowCount < maxValue)
- npRowCount.setText(String.valueOf(++rowCount));
- break;
- case R.id.number_picker_cols_positive:
- if(colCount < maxValue)
- npColCount.setText(String.valueOf(++colCount));
- break;
+ final int id = v.getId();
+ if (id == R.id.number_picker_rows_positive && rowCount < maxValue) {
+ npRowCount.setText(String.valueOf(++rowCount));
+ } else if (id == R.id.number_picker_cols_positive && colCount < maxValue) {
+ npColCount.setText(String.valueOf(++colCount));
}
}
};
@@ -261,15 +240,11 @@ class FormattingController implements View.OnClickListener {
public void onClick(View v) {
int rowCount = Integer.parseInt(npRowCount.getText().toString());
int colCount = Integer.parseInt(npColCount.getText().toString());
- switch (v.getId()){
- case R.id.number_picker_rows_negative:
- if(rowCount > minValue)
- npRowCount.setText(String.valueOf(--rowCount));
- break;
- case R.id.number_picker_cols_negative:
- if(colCount > minValue)
- npColCount.setText(String.valueOf(--colCount));
- break;
+ final int id = v.getId();
+ if (id == R.id.number_picker_rows_negative && rowCount > minValue) {
+ npRowCount.setText(String.valueOf(--rowCount));
+ } else if (id == R.id.number_picker_cols_negative && colCount > minValue) {
+ npColCount.setText(String.valueOf(--colCount));
}
}
};
@@ -421,15 +396,14 @@ class FormattingController implements View.OnClickListener {
void handleActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PHOTO && resultCode == Activity.RESULT_OK) {
- mContext.pendingInsertGraphic = true;
+ compressAndInsertImage();
} else if (requestCode == SELECT_PHOTO && resultCode == Activity.RESULT_OK) {
getFileFromURI(data.getData());
- mContext.pendingInsertGraphic = true;
+ compressAndInsertImage();
}
}
- // Called by LOKitTileProvider when activity is resumed from photo/gallery/camera/cloud apps
- void popCompressImageGradeSelection() {
+ void compressAndInsertImage() {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
String[] options = {mContext.getResources().getString(R.string.compress_photo_smallest_size),
mContext.getResources().getString(R.string.compress_photo_medium_size),
@@ -493,7 +467,6 @@ class FormattingController implements View.OnClickListener {
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:InsertGraphic", rootJson.toString()));
LOKitShell.sendEvent(new LOEvent(LOEvent.REFRESH));
mContext.setDocumentChanged(true);
- mContext.pendingInsertGraphic = false;
}
private void compressImage(int grade) {
diff --git a/android/source/src/java/org/libreoffice/InvalidationHandler.java b/android/source/src/java/org/libreoffice/InvalidationHandler.java
index 32e9b56656dd..c48127cce67f 100644
--- a/android/source/src/java/org/libreoffice/InvalidationHandler.java
+++ b/android/source/src/java/org/libreoffice/InvalidationHandler.java
@@ -25,12 +25,12 @@ import java.util.List;
* Parses (interprets) and handles invalidation messages from LibreOffice.
*/
public class InvalidationHandler implements Document.MessageCallback, Office.MessageCallback {
- private static String LOGTAG = InvalidationHandler.class.getSimpleName();
+ private static final String LOGTAG = InvalidationHandler.class.getSimpleName();
private final DocumentOverlay mDocumentOverlay;
private final GeckoLayerClient mLayerClient;
private OverlayState mState;
private boolean mKeyEvent = false;
- private LibreOfficeMainActivity mContext;
+ private final LibreOfficeMainActivity mContext;
private int currentTotalPageNumber = 0; // total page number of the current document
@@ -55,6 +55,7 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
&& messageID != Document.CALLBACK_DOCUMENT_PASSWORD
&& messageID != Document.CALLBACK_HYPERLINK_CLICKED
&& messageID != Document.CALLBACK_SEARCH_RESULT_SELECTION
+ && messageID != Document.CALLBACK_SC_FOLLOW_JUMP
&& messageID != Document.CALLBACK_TEXT_SELECTION
&& messageID != Document.CALLBACK_TEXT_SELECTION_START
&& messageID != Document.CALLBACK_TEXT_SELECTION_END)
@@ -114,6 +115,9 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
case Document.CALLBACK_CELL_CURSOR:
invalidateCellCursor(payload);
break;
+ case Document.CALLBACK_SC_FOLLOW_JUMP:
+ jumpToCell(payload);
+ break;
case Document.CALLBACK_INVALIDATE_HEADER:
invalidateHeader();
break;
@@ -139,7 +143,7 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
JSONObject payloadObject = new JSONObject(payload);
if (payloadObject.getString("commandName").equals(".uno:Save")) {
if (payloadObject.getString("success").equals("true")) {
- mContext.saveFilesToCloud();
+ mContext.saveFileToOriginalSource();
}
}else if(payloadObject.getString("commandName").equals(".uno:Name") ||
payloadObject.getString("commandName").equals(".uno:RenamePage")){
@@ -214,6 +218,14 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
}
}
+ private void jumpToCell(String payload) {
+ RectF cellCursorRect = convertPayloadCellToRectangle(payload);
+
+ if (cellCursorRect != null) {
+ moveViewportToMakeSelectionVisible(cellCursorRect);
+ }
+ }
+
/**
* Handles the search result selection message, which is a JSONObject
*
@@ -330,7 +342,7 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
mContext.getFormattingController().onToggleStateChanged(Document.NUMBERED_LIST, pressed);
} else if (parts[0].equals(".uno:Color")) {
mContext.getFontController().colorPaletteListener.updateColorPickerPosition(Integer.parseInt(value));
- } else if (mContext.getTileProvider().isTextDocument() && parts[0].equals(".uno:BackColor")) {
+ } else if (mContext.getTileProvider().isTextDocument() && (parts[0].equals(".uno:BackColor") || parts[0].equals(".uno:CharBackColor"))) {
mContext.getFontController().backColorPaletteListener.updateColorPickerPosition(Integer.parseInt(value));
} else if (mContext.getTileProvider().isPresentation() && parts[0].equals(".uno:CharBackColor")) {
mContext.getFontController().backColorPaletteListener.updateColorPickerPosition(Integer.parseInt(value));
@@ -368,6 +380,40 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
if (coordinates.length != 4) {
return null;
}
+ return convertPayloadToRectangle(coordinates);
+ }
+
+ /**
+ * Parses the payload text with rectangle coordinates and converts to rectangle in pixel coordinates
+ *
+ * @param payload - invalidation message payload text
+ * @return rectangle in pixel coordinates
+ */
+ public RectF convertPayloadCellToRectangle(String payload) {
+ String payloadWithoutWhitespace = payload.replaceAll("\\s", ""); // remove all whitespace from the string
+
+ if (payloadWithoutWhitespace.isEmpty() || payloadWithoutWhitespace.equals("EMPTY")) {
+ return null;
+ }
+
+ String[] coordinates = payloadWithoutWhitespace.split(",");
+
+ if (coordinates.length != 6 ) {
+ return null;
+ }
+ return convertPayloadToRectangle(coordinates);
+ }
+
+ /**
+ * Converts rectangle coordinates to rectangle in pixel coordinates
+ *
+ * @param coordinates - the first four items defines the rectangle
+ * @return rectangle in pixel coordinates
+ */
+ public RectF convertPayloadToRectangle(String[] coordinates) {
+ if (coordinates.length < 4 ) {
+ return null;
+ }
int x = Integer.decode(coordinates[0]);
int y = Integer.decode(coordinates[1]);
@@ -377,10 +423,10 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
float dpi = LOKitShell.getDpi(mContext);
return new RectF(
- LOKitTileProvider.twipToPixel(x, dpi),
- LOKitTileProvider.twipToPixel(y, dpi),
- LOKitTileProvider.twipToPixel(x + width, dpi),
- LOKitTileProvider.twipToPixel(y + height, dpi)
+ LOKitTileProvider.twipToPixel(x, dpi),
+ LOKitTileProvider.twipToPixel(y, dpi),
+ LOKitTileProvider.twipToPixel(x + width, dpi),
+ LOKitTileProvider.twipToPixel(y + height, dpi)
);
}
@@ -505,7 +551,7 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
changeStateTo(OverlayState.TRANSITION);
}
mDocumentOverlay.changeSelections(Collections.<RectF>emptyList());
- if (mContext.isSpreadsheet()) {
+ if (mContext.getTileProvider().isSpreadsheet()) {
mDocumentOverlay.showHeaderSelection(null);
}
mContext.getToolbarController().showHideClipboardCutAndCopy(false);
@@ -516,7 +562,7 @@ public class InvalidationHandler implements Document.MessageCallback, Office.Mes
}
changeStateTo(OverlayState.SELECTION);
mDocumentOverlay.changeSelections(rectangles);
- if (mContext.isSpreadsheet()) {
+ if (mContext.getTileProvider().isSpreadsheet()) {
mDocumentOverlay.showHeaderSelection(rectangles.get(0));
}
String selectedText = mContext.getTileProvider().getTextSelection("");
diff --git a/android/source/src/java/org/libreoffice/LOEvent.java b/android/source/src/java/org/libreoffice/LOEvent.java
index 4db48a5bbd6d..d1170eee12ad 100644
--- a/android/source/src/java/org/libreoffice/LOEvent.java
+++ b/android/source/src/java/org/libreoffice/LOEvent.java
@@ -33,7 +33,6 @@ public class LOEvent implements Comparable<LOEvent> {
public static final int SWIPE_LEFT = 12;
public static final int NAVIGATION_CLICK = 13;
public static final int UNO_COMMAND = 14;
- public static final int RESUME = 15;
public static final int LOAD_NEW = 16;
public static final int SAVE_AS = 17;
public static final int UPDATE_PART_PAGE_RECT = 18;
@@ -42,6 +41,7 @@ public class LOEvent implements Comparable<LOEvent> {
public static final int REFRESH = 21;
public static final int PAGE_SIZE_CHANGED = 22;
public static final int UNO_COMMAND_NOTIFY = 23;
+ public static final int SAVE_COPY_AS = 24;
public final int mType;
@@ -104,13 +104,6 @@ public class LOEvent implements Comparable<LOEvent> {
mValue = value;
}
- public LOEvent(int type, String key, int value) {
- mType = type;
- mTypeString = "Resume partIndex";
- mString = key;
- mPartIndex = value;
- }
-
public LOEvent(String filePath, int type) {
mType = type;
mTypeString = "Load";
diff --git a/android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java b/android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java
index bbef709af297..7b50ef5ff707 100644
--- a/android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java
+++ b/android/source/src/java/org/libreoffice/LOKitInputConnectionHandler.java
@@ -19,7 +19,7 @@ import org.mozilla.gecko.gfx.InputConnectionHandler;
* directed to this class which is then directed further to LOKitThread.
*/
public class LOKitInputConnectionHandler implements InputConnectionHandler {
- private static String LOGTAG = LOKitInputConnectionHandler.class.getSimpleName();
+ private static final String LOGTAG = LOKitInputConnectionHandler.class.getSimpleName();
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
diff --git a/android/source/src/java/org/libreoffice/LOKitShell.java b/android/source/src/java/org/libreoffice/LOKitShell.java
index c69e02669619..f6a76228e008 100644
--- a/android/source/src/java/org/libreoffice/LOKitShell.java
+++ b/android/source/src/java/org/libreoffice/LOKitShell.java
@@ -24,10 +24,10 @@ import org.mozilla.gecko.gfx.ComposedTileLayer;
* Common static LOKit functions, functions to send events.
*/
public class LOKitShell {
- private static final String LOGTAG = LOKitShell.class.getSimpleName();
-
public static float getDpi(Context context) {
- if (((LibreOfficeMainActivity)context).isSpreadsheet()) return 96f;
+ LOKitTileProvider tileProvider = ((LibreOfficeMainActivity)context).getTileProvider();
+ if (tileProvider != null && tileProvider.isSpreadsheet())
+ return 96f;
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return metrics.density * 160;
}
@@ -61,7 +61,7 @@ public class LOKitShell {
}
public static boolean isEditingEnabled() {
- return LibreOfficeMainActivity.isExperimentalMode();
+ return !LibreOfficeMainActivity.isReadOnlyMode();
}
// EVENTS
@@ -119,8 +119,8 @@ public class LOKitShell {
LOKitShell.sendEvent(new LOEvent(filePath, fileFormat, LOEvent.SAVE_AS));
}
- public static void sendResumeEvent(String inputFile, int partIndex) {
- LOKitShell.sendEvent(new LOEvent(LOEvent.RESUME, inputFile, partIndex));
+ public static void sendSaveCopyAsEvent(String filePath, String fileFormat) {
+ LOKitShell.sendEvent(new LOEvent(filePath, fileFormat, LOEvent.SAVE_COPY_AS));
}
public static void sendCloseEvent() {
diff --git a/android/source/src/java/org/libreoffice/LOKitThread.java b/android/source/src/java/org/libreoffice/LOKitThread.java
index e554f0800cf0..fd40c3089102 100644
--- a/android/source/src/java/org/libreoffice/LOKitThread.java
+++ b/android/source/src/java/org/libreoffice/LOKitThread.java
@@ -7,7 +7,6 @@ import android.util.Log;
import android.view.KeyEvent;
import org.libreoffice.canvas.SelectionHandle;
-import org.libreoffice.ui.LibreOfficeUIActivity;
import org.mozilla.gecko.ZoomConstraints;
import org.mozilla.gecko.gfx.CairoImage;
import org.mozilla.gecko.gfx.ComposedTileLayer;
@@ -26,13 +25,13 @@ import java.util.concurrent.LinkedBlockingQueue;
class LOKitThread extends Thread {
private static final String LOGTAG = LOKitThread.class.getSimpleName();
- private LinkedBlockingQueue<LOEvent> mEventQueue = new LinkedBlockingQueue<LOEvent>();
+ private final LinkedBlockingQueue<LOEvent> mEventQueue = new LinkedBlockingQueue<LOEvent>();
private TileProvider mTileProvider;
private InvalidationHandler mInvalidationHandler;
private ImmutableViewportMetrics mViewportMetrics;
private GeckoLayerClient mLayerClient;
- private LibreOfficeMainActivity mContext;
+ private final LibreOfficeMainActivity mContext;
LOKitThread(LibreOfficeMainActivity context) {
mContext = context;
@@ -112,7 +111,7 @@ class LOKitThread extends Thread {
/**
* Handle the geometry change + draw.
*/
- private void redraw() {
+ private void redraw(boolean resetZoomAndPosition) {
if (mLayerClient == null || mTileProvider == null) {
// called too early...
return;
@@ -122,7 +121,9 @@ class LOKitThread extends Thread {
mViewportMetrics = mLayerClient.getViewportMetrics();
mLayerClient.setViewportMetrics(mViewportMetrics);
- zoomAndRepositionTheDocument();
+ if (resetZoomAndPosition) {
+ zoomAndRepositionTheDocument();
+ }
mLayerClient.forceRedraw();
mLayerClient.forceRender();
@@ -152,9 +153,9 @@ class LOKitThread extends Thread {
/**
* Invalidate everything + handle the geometry change
*/
- private void refresh() {
+ private void refresh(boolean resetZoomAndPosition) {
mLayerClient.clearAndResetlayers();
- redraw();
+ redraw(resetZoomAndPosition);
updatePartPageRectangles();
if (mTileProvider != null && mTileProvider.isSpreadsheet()) {
updateCalcHeaders();
@@ -177,35 +178,17 @@ class LOKitThread extends Thread {
private void updatePageSize(int pageWidth, int pageHeight){
mTileProvider.setDocumentSize(pageWidth, pageHeight);
- redraw();
+ redraw(true);
}
private void updateZoomConstraints() {
if (mTileProvider == null) return;
mLayerClient = mContext.getLayerClient();
- // Set min zoom to the page width so that you cannot zoom below page width
- final float minZoom = mLayerClient.getViewportMetrics().getWidth()/mTileProvider.getPageWidth();
- mLayerClient.setZoomConstraints(new ZoomConstraints(true, 1f, minZoom, 0f));
- }
-
-
- /**
- * Resume the document with the current part
- */
-
- private void resumeDocument(String filename, int partIndex){
-
- mLayerClient = mContext.getLayerClient();
-
- mInvalidationHandler = new InvalidationHandler(mContext);
- mTileProvider = TileProviderFactory.create(mContext, mInvalidationHandler, filename);
-
- if (mTileProvider.isReady()) {
- updateZoomConstraints();
- changePart(partIndex);
- } else {
- closeDocument();
- }
+ // Set default zoom to the page width and min zoom so that the whole page is visible
+ final float pageHeightZoom = mLayerClient.getViewportMetrics().getHeight() / mTileProvider.getPageHeight();
+ final float pageWidthZoom = mLayerClient.getViewportMetrics().getWidth() / mTileProvider.getPageWidth();
+ final float minZoom = Math.min(pageWidthZoom, pageHeightZoom);
+ mLayerClient.setZoomConstraints(new ZoomConstraints(pageWidthZoom, minZoom, 0f));
}
/**
@@ -216,15 +199,16 @@ class LOKitThread extends Thread {
mTileProvider.changePart(partIndex);
mViewportMetrics = mLayerClient.getViewportMetrics();
// mLayerClient.setViewportMetrics(mViewportMetrics.scaleTo(0.9f, new PointF()));
- refresh();
+ refresh(true);
LOKitShell.hideProgressSpinner(mContext);
}
/**
* Handle load document event.
* @param filePath - filePath to where the document is located
+ * @return Whether the document has been loaded successfully.
*/
- private void loadDocument(String filePath) {
+ private boolean loadDocument(String filePath) {
mLayerClient = mContext.getLayerClient();
mInvalidationHandler = new InvalidationHandler(mContext);
@@ -233,18 +217,12 @@ class LOKitThread extends Thread {
if (mTileProvider.isReady()) {
LOKitShell.showProgressSpinner(mContext);
updateZoomConstraints();
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- // synchronize to avoid deletion while loading
- synchronized (LOKitThread.this) {
- refresh();
- }
- }
- });
+ refresh(true);
LOKitShell.hideProgressSpinner(mContext);
+ return true;
} else {
closeDocument();
+ return false;
}
}
@@ -254,47 +232,27 @@ class LOKitThread extends Thread {
* @param fileType - fileType what type of new document is to be loaded
*/
private void loadNewDocument(String filePath, String fileType) {
- mLayerClient = mContext.getLayerClient();
-
- mInvalidationHandler = new InvalidationHandler(mContext);
- mTileProvider = TileProviderFactory.create(mContext, mInvalidationHandler, fileType);
-
- if (mTileProvider.isReady()) {
- LOKitShell.showProgressSpinner(mContext);
- updateZoomConstraints();
- refresh();
- LOKitShell.hideProgressSpinner(mContext);
-
- if (fileType.matches(LibreOfficeUIActivity.NEW_WRITER_STRING_KEY))
- mTileProvider.saveDocumentAs(filePath, "odt");
- else if (fileType.matches(LibreOfficeUIActivity.NEW_CALC_STRING_KEY))
- mTileProvider.saveDocumentAs(filePath, "ods");
- else if (fileType.matches(LibreOfficeUIActivity.NEW_IMPRESS_STRING_KEY))
- mTileProvider.saveDocumentAs(filePath, "odp");
- else
- mTileProvider.saveDocumentAs(filePath, "odg");
-
- } else {
- closeDocument();
+ boolean ok = loadDocument(fileType);
+ if (ok) {
+ mTileProvider.saveDocumentAs(filePath, true);
}
}
/**
* Save the currently loaded document.
*/
- private void saveDocumentAs(String filePath, String fileType) {
+ private void saveDocumentAs(String filePath, String fileType, boolean bTakeOwnership) {
if (mTileProvider == null) {
Log.e(LOGTAG, "Error in saving, Tile Provider instance is null");
} else {
- mTileProvider.saveDocumentAs(filePath, fileType);
+ mTileProvider.saveDocumentAs(filePath, fileType, bTakeOwnership);
}
}
/**
* Close the currently loaded document.
*/
- // needs to be synchronized to not destroy doc while it's loaded
- private synchronized void closeDocument() {
+ private void closeDocument() {
if (mTileProvider != null) {
mTileProvider.close();
mTileProvider = null;
@@ -313,16 +271,16 @@ class LOKitThread extends Thread {
loadNewDocument(event.filePath, event.fileType);
break;
case LOEvent.SAVE_AS:
- saveDocumentAs(event.filePath, event.fileType);
+ saveDocumentAs(event.filePath, event.fileType, true);
break;
- case LOEvent.RESUME:
- resumeDocument(event.mString, event.mPartIndex);
+ case LOEvent.SAVE_COPY_AS:
+ saveDocumentAs(event.filePath, event.fileType, false);
break;
case LOEvent.CLOSE:
closeDocument();
break;
case LOEvent.SIZE_CHANGED:
- redraw();
+ redraw(false);
break;
case LOEvent.CHANGE_PART:
changePart(event.mPartIndex);
@@ -376,7 +334,7 @@ class LOKitThread extends Thread {
mTileProvider.postUnoCommand(event.mString, event.mValue, event.mNotify);
break;
case LOEvent.REFRESH:
- refresh();
+ refresh(false);
break;
case LOEvent.PAGE_SIZE_CHANGED:
updatePageSize(event.mPageWidth, event.mPageHeight);
@@ -448,7 +406,7 @@ class LOKitThread extends Thread {
boolean editing = LOKitShell.isEditingEnabled();
float zoomFactor = mViewportMetrics.getZoomFactor();
- if (touchType.equals("LongPress") && editing) {
+ if (touchType.equals("LongPress")) {
mInvalidationHandler.changeStateTo(InvalidationHandler.OverlayState.TRANSITION);
mTileProvider.mouseButtonDown(documentCoordinate, 1, zoomFactor);
mTileProvider.mouseButtonUp(documentCoordinate, 1, zoomFactor);
diff --git a/android/source/src/java/org/libreoffice/LOKitTileProvider.java b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
index 0e2649337322..5d1cf12209dc 100644
--- a/android/source/src/java/org/libreoffice/LOKitTileProvider.java
+++ b/android/source/src/java/org/libreoffice/LOKitTileProvider.java
@@ -12,7 +12,6 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.os.Build;
-import android.os.Environment;
import android.print.PrintAttributes;
import android.print.PrintDocumentAdapter;
import android.print.PrintManager;
@@ -26,7 +25,6 @@ import org.libreoffice.kit.DirectBufferAllocator;
import org.libreoffice.kit.Document;
import org.libreoffice.kit.LibreOfficeKit;
import org.libreoffice.kit.Office;
-import org.libreoffice.ui.FileUtilities;
import org.mozilla.gecko.gfx.BufferedCairoImage;
import org.mozilla.gecko.gfx.CairoImage;
import org.mozilla.gecko.gfx.IntSize;
@@ -39,22 +37,22 @@ import java.nio.ByteBuffer;
*/
class LOKitTileProvider implements TileProvider {
private static final String LOGTAG = LOKitTileProvider.class.getSimpleName();
- private static int TILE_SIZE = 256;
+ private static final int TILE_SIZE = 256;
private final float mTileWidth;
private final float mTileHeight;
- private final String mInputFile;
+ private String mInputFile;
private Office mOffice;
private Document mDocument;
- private boolean mIsReady = false;
- private LibreOfficeMainActivity mContext;
+ private final boolean mIsReady;
+ private final LibreOfficeMainActivity mContext;
- private float mDPI;
+ private final float mDPI;
private float mWidthTwip;
private float mHeightTwip;
- private Document.MessageCallback mMessageCallback;
+ private final Document.MessageCallback mMessageCallback;
- private long objectCreationTime = System.currentTimeMillis();
+ private final long objectCreationTime = System.currentTimeMillis();
/**
* Initialize LOKit and load the document.
@@ -73,32 +71,16 @@ class LOKitTileProvider implements TileProvider {
mOffice.setOptionalFeatures(Document.LOK_FEATURE_DOCUMENT_PASSWORD);
mContext.setTileProvider(this);
mInputFile = input;
- File f = new File(mInputFile);
- final String cacheFile = mContext.getExternalCacheDir().getAbsolutePath() + "/lo_cached_" + f.getName();
-
- if(mContext.firstStart){
- File cacheFileObj = new File(cacheFile);
- if(cacheFileObj.exists()) {
- cacheFileObj.delete();
- }
- mContext.firstStart=false;
- }
Log.i(LOGTAG, "====> Loading file '" + input + "'");
- File fileToBeEncoded;
- if(isDocumentCached()){
- fileToBeEncoded = new File(cacheFile);
- }else{
- fileToBeEncoded = new File(input);
- }
+ File fileToBeEncoded = new File(input);
String encodedFileName = android.net.Uri.encode(fileToBeEncoded.getName());
mDocument = mOffice.documentLoad(
(new File(fileToBeEncoded.getParent(),encodedFileName)).getPath()
);
-
if (mDocument == null && !mContext.isPasswordProtected()) {
Log.i(LOGTAG, "====> mOffice.documentLoad() returned null, trying to restart 'Office' and loading again");
mOffice.destroy();
@@ -117,10 +99,6 @@ class LOKitTileProvider implements TileProvider {
Log.i(LOGTAG, "====> mDocument = " + mDocument);
- if(isSpreadsheet()) {
- mContext.setIsSpreadsheet(true); // Calc is treated differently e.g. DPI = 96f
- }
-
mDPI = LOKitShell.getDpi(mContext);
mTileWidth = pixelToTwip(TILE_SIZE, mDPI);
mTileHeight = pixelToTwip(TILE_SIZE, mDPI);
@@ -142,27 +120,9 @@ class LOKitTileProvider implements TileProvider {
private void postLoad() {
mDocument.setMessageCallback(mMessageCallback);
- int parts = mDocument.getParts();
- Log.i(LOGTAG, "Document parts: " + parts);
- mContext.getDocumentPartView().clear();
-
+ resetParts();
// Writer documents always have one part, so hide the navigation drawer.
- if (mDocument.getDocumentType() != Document.DOCTYPE_TEXT) {
- for (int i = 0; i < parts; i++) {
- String partName = mDocument.getPartName(i);
- if (partName.isEmpty()) {
- partName = getGenericPartName(i);
- }else if (partName.startsWith("Slide") || partName.startsWith("Sheet") || partName.startsWith("Part")) {
- partName = getGenericPartName(i);
- }
- Log.i(LOGTAG, "Document part " + i + " name:'" + partName + "'");
-
- mDocument.setPart(i);
- resetDocumentSize();
- final DocumentPartView partView = new DocumentPartView(i, partName);
- mContext.getDocumentPartView().add(partView);
- }
- } else {
+ if (mDocument.getDocumentType() == Document.DOCTYPE_TEXT) {
mContext.disableNavigationDrawer();
mContext.getToolbarController().hideItem(R.id.action_parts);
}
@@ -182,14 +142,6 @@ class LOKitTileProvider implements TileProvider {
mContext.getDocumentPartViewListAdapter().notifyDataSetChanged();
}
});
- mContext.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (mContext.pendingInsertGraphic) {
- mContext.getFormattingController().popCompressImageGradeSelection();
- }
- }
- });
}
public void addPart(){
@@ -224,9 +176,9 @@ class LOKitTileProvider implements TileProvider {
}
public void resetParts(){
- int parts = mDocument.getParts();
mContext.getDocumentPartView().clear();
if (mDocument.getDocumentType() != Document.DOCTYPE_TEXT) {
+ int parts = mDocument.getParts();
for (int i = 0; i < parts; i++) {
String partName = mDocument.getPartName(i);
@@ -240,7 +192,9 @@ class LOKitTileProvider implements TileProvider {
mContext.getDocumentPartView().add(partView);
}
}
- } public void renamePart(String partName) {
+ }
+
+ public void renamePart(String partName) {
try{
for(int i=0; i<mDocument.getParts(); i++){
if(mContext.getDocumentPartView().get(i).partName.equals(partName)){
@@ -270,7 +224,7 @@ class LOKitTileProvider implements TileProvider {
public void removePart() {
try{
- if(isSpreadsheet() == false && isPresentation() == false) {
+ if (!isSpreadsheet() && !isPresentation()) {
//document must be spreadsheet or presentation
return;
}
@@ -295,38 +249,37 @@ class LOKitTileProvider implements TileProvider {
}
}
-
-
@Override
- public void saveDocumentAs(final String filePath, String format) {
+ public boolean saveDocumentAs(final String filePath, String format, boolean takeOwnership) {
+ String options = "";
+ if (takeOwnership) {
+ options = "TakeOwnership";
+ }
+
final String newFilePath = "file://" + filePath;
Log.d("saveFilePathURL", newFilePath);
LOKitShell.showProgressSpinner(mContext);
- mDocument.saveAs(newFilePath, format, "");
+ mDocument.saveAs(newFilePath, format, options);
+ final boolean ok;
if (!mOffice.getError().isEmpty()){
+ ok = true;
Log.e("Save Error", mOffice.getError());
if (format.equals("svg")) {
// error in creating temp slideshow svg file
Log.d(LOGTAG, "Error in creating temp slideshow svg file");
} else if(format.equals("pdf")){
Log.d(LOGTAG, "Error in creating pdf file");
+ } else {
LOKitShell.getMainHandler().post(new Runnable() {
@Override
public void run() {
// There was some error
- mContext.showCustomStatusMessage(mContext.getString(R.string.unable_to_export_pdf));
- }
- });
- }else {
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- // There was some error
- mContext.showSaveStatusMessage(true);
+ mContext.showCustomStatusMessage(mContext.getString(R.string.unable_to_save));
}
});
}
} else {
+ ok = false;
if (format.equals("svg")) {
// successfully created temp slideshow svg file
LOKitShell.getMainHandler().post(new Runnable() {
@@ -335,99 +288,49 @@ class LOKitTileProvider implements TileProvider {
mContext.startPresentation(newFilePath);
}
});
- }else if(format.equals("pdf")){
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- // There was no error
- mContext.showCustomStatusMessage(mContext.getString(R.string.pdf_exported_at)+filePath);
- }
- });
- } else {
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- // There was no error
- mContext.showSaveStatusMessage(false);
- }
- });
+ } else if (takeOwnership) {
+ mInputFile = filePath;
}
}
LOKitShell.hideProgressSpinner(mContext);
+ return ok;
}
- public void exportToPDF(boolean print){
- String dir = Environment.getExternalStorageDirectory().getAbsolutePath()+"/Documents";
- File docDir = new File(dir);
- if(!docDir.exists()){
- docDir.mkdir();
- }
- String mInputFileName = (new File(mInputFile)).getName();
- String file = mInputFileName.substring(0,(mInputFileName.length()-3))+"pdf";
- if(print){
- String cacheFile = mContext.getExternalCacheDir().getAbsolutePath()
- + "/" + file;
- mDocument.saveAs("file://"+cacheFile,"pdf","");
- printDocument(cacheFile);
- }else{
- saveDocumentAs(dir+"/"+file,"pdf");
- }
- }
-
- private void printDocument(String cacheFile) {
- if (Build.VERSION.SDK_INT >= 19) {
- try {
- PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
- PrintDocumentAdapter printAdapter = new PDFDocumentAdapter(mContext, cacheFile);
- printManager.print("Document", printAdapter, new PrintAttributes.Builder().build());
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- } else {
- mContext.showCustomStatusMessage(mContext.getString(R.string.printing_not_supported));
- }
- }
-
- public boolean isDocumentCached(){
- File input = new File(mInputFile);
- final String cacheFile = mContext.getExternalCacheDir().getAbsolutePath() + "/lo_cached_" + input.getName();
- File cacheFileObj = new File(cacheFile);
- if(cacheFileObj.exists())
- return true;
-
+ @Override
+ public boolean saveDocumentAs(final String filePath, boolean takeOwnership) {
+ final int docType = mDocument.getDocumentType();
+ if (docType == Document.DOCTYPE_TEXT)
+ return saveDocumentAs(filePath, "odt", takeOwnership);
+ else if (docType == Document.DOCTYPE_SPREADSHEET)
+ return saveDocumentAs(filePath, "ods", takeOwnership);
+ else if (docType == Document.DOCTYPE_PRESENTATION)
+ return saveDocumentAs(filePath, "odp", takeOwnership);
+ else if (docType == Document.DOCTYPE_DRAWING)
+ return saveDocumentAs(filePath, "odg", takeOwnership);
+
+ Log.w(LOGTAG, "Cannot determine file format from document. Not saving.");
return false;
}
- public void cacheDocument() {
- String cacheDir = mContext.getExternalCacheDir().getAbsolutePath();
- File input = new File(mInputFile);
- final String cacheFile = cacheDir + "/lo_cached_" + input.getName();
- Log.i(LOGTAG, "cacheDocument: " + cacheFile);
- if(isDocumentCached()){
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Save"));
- }else if(mDocument != null){
- mDocument.saveAs("file://"+cacheFile, FileUtilities.getExtension(input.getPath()).substring(1),"");
- }else{
- Log.w(LOGTAG, "mDocument was null when trying to save cacheDocument: " + cacheFile);
+ public void printDocument() {
+ String mInputFileName = (new File(mInputFile)).getName();
+ String file = mInputFileName.substring(0,(mInputFileName.length()-3))+"pdf";
+ String cacheFile = mContext.getExternalCacheDir().getAbsolutePath() + "/" + file;
+ mDocument.saveAs("file://"+cacheFile,"pdf","");
+ try {
+ PrintManager printManager = (PrintManager) mContext.getSystemService(Context.PRINT_SERVICE);
+ PrintDocumentAdapter printAdapter = new PDFDocumentAdapter(mContext, cacheFile);
+ printManager.print("Document", printAdapter, new PrintAttributes.Builder().build());
+
+ } catch (Exception e) {
+ e.printStackTrace();
}
}
public void saveDocument(){
- if(isDocumentCached()){
- String format = FileUtilities.getExtension(mInputFile).substring(1);
- String cacheDir = mContext.getExternalCacheDir().getAbsolutePath();
- File input = new File(mInputFile);
- final String cacheFile = cacheDir + "/lo_cached_" + input.getName();
- String path = input.getAbsolutePath();
- saveDocumentAs(path, format);
- (new File(cacheFile)).delete();
- }else{
- mContext.saveDocument();
- }
+ mContext.saveDocument();
}
-
private void setupDocumentFonts() {
String values = mDocument.getCommandValues(".uno:CharFontName");
if (values == null || values.isEmpty())
@@ -674,6 +577,14 @@ class LOKitTileProvider implements TileProvider {
}
/**
+ * @see TileProvider#isDrawing()
+ */
+ @Override
+ public boolean isDrawing() {
+ return mDocument != null && mDocument.getDocumentType() == Document.DOCTYPE_DRAWING;
+ }
+
+ /**
* @see TileProvider#isTextDocument()
*/
@Override
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeApplication.java b/android/source/src/java/org/libreoffice/LibreOfficeApplication.java
index cb79219fc999..ebe54cf27c64 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeApplication.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeApplication.java
@@ -10,11 +10,11 @@
package org.libreoffice;
-import android.app.Application;
import android.content.Context;
import android.os.Handler;
+import androidx.multidex.MultiDexApplication;
-public class LibreOfficeApplication extends Application {
+public class LibreOfficeApplication extends MultiDexApplication {
private static Handler mainHandler;
diff --git a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
index cbc628e94e48..cf60ff37c5da 100644
--- a/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
+++ b/android/source/src/java/org/libreoffice/LibreOfficeMainActivity.java
@@ -1,6 +1,5 @@
package org.libreoffice;
-import android.app.Activity;
import android.app.AlertDialog;
import android.content.ClipData;
import android.content.ClipboardManager;
@@ -9,19 +8,18 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.graphics.RectF;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.support.design.widget.BottomSheetBehavior;
-import android.support.design.widget.Snackbar;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.Toolbar;
+import android.provider.DocumentsContract;
+import com.google.android.material.bottomsheet.BottomSheetBehavior;
+import com.google.android.material.snackbar.Snackbar;
+import androidx.drawerlayout.widget.DrawerLayout;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.Toolbar;
import android.text.InputType;
import android.util.Log;
import android.view.KeyEvent;
@@ -36,24 +34,25 @@ import android.widget.Toast;
import org.libreoffice.overlay.CalcHeadersController;
import org.libreoffice.overlay.DocumentOverlay;
-import org.libreoffice.storage.DocumentProviderFactory;
-import org.libreoffice.storage.IFile;
import org.libreoffice.ui.FileUtilities;
import org.libreoffice.ui.LibreOfficeUIActivity;
import org.mozilla.gecko.gfx.GeckoLayerClient;
import org.mozilla.gecko.gfx.LayerView;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.net.URI;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
/**
* Main activity of the LibreOffice App. It is started in the UI thread.
@@ -61,10 +60,11 @@ import java.util.List;
public class LibreOfficeMainActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener {
private static final String LOGTAG = "LibreOfficeMainActivity";
- private static final String DEFAULT_DOC_PATH = "/assets/example.odt";
- private static final String ENABLE_EXPERIMENTAL_PREFS_KEY = "ENABLE_EXPERIMENTAL";
+ public static final String ENABLE_EXPERIMENTAL_PREFS_KEY = "ENABLE_EXPERIMENTAL";
private static final String ASSETS_EXTRACTED_PREFS_KEY = "ASSETS_EXTRACTED";
private static final String ENABLE_DEVELOPER_PREFS_KEY = "ENABLE_DEVELOPER";
+ private static final int REQUEST_CODE_SAVEAS = 12345;
+ private static final int REQUEST_CODE_EXPORT_TO_PDF = 12346;
//TODO "public static" is a temporary workaround
public static LOKitThread loKitThread;
@@ -73,23 +73,20 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
private static boolean mIsExperimentalMode;
private static boolean mIsDeveloperMode;
-
- private int providerId;
- private URI documentUri;
+ private static boolean mbISReadOnlyMode;
private DrawerLayout mDrawerLayout;
Toolbar toolbarTop;
private ListView mDrawerList;
- private List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
+ private final List<DocumentPartView> mDocumentPartView = new ArrayList<DocumentPartView>();
private DocumentPartViewListAdapter mDocumentPartViewListAdapter;
- private int partIndex=-1;
- private File mInputFile;
private DocumentOverlay mDocumentOverlay;
+ /** URI to save the document to. */
+ private Uri mDocumentUri;
+ /** Temporary local copy of the document. */
private File mTempFile = null;
private File mTempSlideShowFile = null;
- private String newDocumentType = null;
- public boolean firstStart = true;
BottomSheetBehavior bottomToolbarSheetBehavior;
BottomSheetBehavior toolbarColorPickerBottomSheetBehavior;
@@ -100,11 +97,10 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
private SearchController mSearchController;
private UNOCommandsController mUNOCommandsController;
private CalcHeadersController mCalcHeadersController;
- private boolean mIsSpreadsheet;
private LOKitTileProvider mTileProvider;
private String mPassword;
private boolean mPasswordProtected;
- public boolean pendingInsertGraphic; // boolean indicating a pending insert graphic action, used in LOKitTileProvider.postLoad()
+ private boolean mbSkipNextRefresh;
public GeckoLayerClient getLayerClient() {
return mLayerClient;
@@ -118,17 +114,11 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
return mIsDeveloperMode;
}
- public boolean usesTemporaryFile() {
- return mTempFile != null;
- }
-
private boolean isKeyboardOpen = false;
private boolean isFormattingToolbarOpen = false;
private boolean isSearchToolbarOpen = false;
private static boolean isDocumentChanged = false;
private boolean isUNOCommandsToolbarOpen = false;
- public boolean isNewDocument = false;
- private long lastModified = 0;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -168,8 +158,8 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
layerView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View view, int i, KeyEvent keyEvent) {
- if(keyEvent.getKeyCode() != KeyEvent.KEYCODE_BACK){
- isDocumentChanged=true;
+ if(!isReadOnlyMode() && keyEvent.getKeyCode() != KeyEvent.KEYCODE_BACK){
+ setDocumentChanged(true);
}
return false;
}
@@ -178,40 +168,54 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
// create TextCursorLayer
mDocumentOverlay = new DocumentOverlay(this, layerView);
- // New document type string is not null, meaning we want to open a new document
- if (getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY) != null) {
- String newDocumentType = getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY);
- String newFilePath = getIntent().getStringExtra(LibreOfficeUIActivity.NEW_FILE_PATH_KEY);
+ mbISReadOnlyMode = !isExperimentalMode();
- // Load the new document
- loadNewDocument(newFilePath, newDocumentType);
- }
+ final Uri docUri = getIntent().getData();
+ if (docUri != null) {
+ if (docUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)
+ || docUri.getScheme().equals(ContentResolver.SCHEME_ANDROID_RESOURCE)) {
+ final boolean isReadOnlyDoc = (getIntent().getFlags() & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
+ mbISReadOnlyMode = !isExperimentalMode() || isReadOnlyDoc;
+ Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + docUri.getPath());
- if (getIntent().getData() != null) {
- if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
- if (copyFileToTemp() && mTempFile != null) {
- mInputFile = mTempFile;
- Log.d(LOGTAG, "SCHEME_CONTENT: getPath(): " + getIntent().getData().getPath());
- toolbarTop.setTitle(mInputFile.getName());
- } else {
- // TODO: can't open the file
- Log.e(LOGTAG, "couldn't create temporary file from " + getIntent().getData());
- }
- } else if (getIntent().getData().getScheme().equals(ContentResolver.SCHEME_FILE)) {
- mInputFile = new File(getIntent().getData().getPath());
- Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + getIntent().getData().getPath());
- toolbarTop.setTitle(mInputFile.getName());
- // Gather data to rebuild IFile object later
- providerId = getIntent().getIntExtra(
- "org.libreoffice.document_provider_id", 0);
- documentUri = (URI) getIntent().getSerializableExtra(
- "org.libreoffice.document_uri");
+ String displayName = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), docUri);
+ toolbarTop.setTitle(displayName);
+
+ } else if (docUri.getScheme().equals(ContentResolver.SCHEME_FILE)) {
+ mbISReadOnlyMode = true;
+ Log.d(LOGTAG, "SCHEME_FILE: getPath(): " + docUri.getPath());
+ toolbarTop.setTitle(docUri.getLastPathSegment());
}
- } else {
- if (!isNewDocument) {
- mInputFile = new File(DEFAULT_DOC_PATH);
+ // create a temporary local copy to work with
+ boolean copyOK = copyFileToTemp(docUri) && mTempFile != null;
+ if (!copyOK) {
+ // TODO: can't open the file
+ Log.e(LOGTAG, "couldn't create temporary file from " + docUri);
+ return;
+ }
+
+ // if input doc is a template, a new doc is created and a proper URI to save to
+ // will only be available after a "Save As"
+ if (isTemplate(docUri)) {
+ toolbarTop.setTitle(R.string.default_document_name);
+ } else {
+ mDocumentUri = docUri;
}
+
+ LOKitShell.sendLoadEvent(mTempFile.getPath());
+ } else if (getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY) != null) {
+ // New document type string is not null, meaning we want to open a new document
+ String newDocumentType = getIntent().getStringExtra(LibreOfficeUIActivity.NEW_DOC_TYPE_KEY);
+ // create a temporary local file, will be copied to the actual URI when saving
+ loadNewDocument(newDocumentType);
+ toolbarTop.setTitle(getString(R.string.default_document_name));
+ } else {
+ Log.e(LOGTAG, "No document specified. This should never happen.");
+ return;
}
+ // the loadDocument/loadNewDocument event already triggers a refresh as well,
+ // so there's no need to do another refresh in 'onStart'
+ mbSkipNextRefresh = true;
mDrawerLayout = findViewById(R.id.drawer_layout);
@@ -223,8 +227,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
mDrawerList.setOnItemClickListener(new DocumentPartClickListener());
}
- lastModified = mInputFile.lastModified();
-
mToolbarController.setupToolbars();
TabHost host = findViewById(R.id.toolbarTabHost);
@@ -274,22 +276,18 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
}
}
- // Loads a new Document
- private void loadNewDocument(String newFilePath, String newDocumentType) {
- mInputFile = new File(newFilePath);
- LOKitShell.sendNewDocumentLoadEvent(newFilePath, newDocumentType);
- isNewDocument = true;
- toolbarTop.setTitle(mInputFile.getName());
+ // Loads a new Document and saves it to a temporary file
+ private void loadNewDocument(String newDocumentType) {
+ String tempFileName = "LibreOffice_" + UUID.randomUUID().toString();
+ mTempFile = new File(this.getCacheDir(), tempFileName);
+ LOKitShell.sendNewDocumentLoadEvent(mTempFile.getPath(), newDocumentType);
}
public RectF getCurrentCursorPosition() {
return mDocumentOverlay.getCurrentCursorPosition();
}
- private boolean copyFileToTemp() {
- ContentResolver contentResolver = getContentResolver();
- FileChannel inputChannel = null;
- FileChannel outputChannel = null;
+ private boolean copyFileToTemp(Uri documentUri) {
// CSV files need a .csv suffix to be opened in Calc.
String suffix = null;
String intentType = getIntent().getType();
@@ -298,27 +296,9 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
suffix = ".csv";
try {
- try {
- AssetFileDescriptor assetFD = contentResolver.openAssetFileDescriptor(getIntent().getData(), "r");
- if (assetFD == null) {
- Log.e(LOGTAG, "couldn't create assetfiledescriptor from " + getIntent().getDataString());
- return false;
- }
- inputChannel = assetFD.createInputStream().getChannel();
- mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
-
- outputChannel = new FileOutputStream(mTempFile).getChannel();
- long bytesTransferred = 0;
- // might not copy all at once, so make sure everything gets copied...
- while (bytesTransferred < inputChannel.size()) {
- bytesTransferred += outputChannel.transferFrom(inputChannel, bytesTransferred, inputChannel.size());
- }
- Log.e(LOGTAG, "Success copying " + bytesTransferred + " bytes");
- return true;
- } finally {
- if (inputChannel != null) inputChannel.close();
- if (outputChannel != null) outputChannel.close();
- }
+ mTempFile = File.createTempFile("LibreOffice", suffix, this.getCacheDir());
+ final FileOutputStream outputStream = new FileOutputStream(mTempFile);
+ return copyUriToStream(documentUri, outputStream);
} catch (FileNotFoundException e) {
return false;
} catch (IOException e) {
@@ -327,65 +307,150 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
}
/**
- * Save a new document
- * */
- public void saveAs(){
- LOKitShell.sendSaveAsEvent(mInputFile.getPath(), FileUtilities.getExtension(mInputFile.getPath()).substring(1));
- }
-
- /**
- * Save the document and invoke save on document provider to upload the file
- * to the cloud if necessary.
+ * Save the document.
*/
public void saveDocument() {
- if (!mInputFile.exists()) {
- // Needed for handling null in case new document is not created.
- mInputFile = new File(DEFAULT_DOC_PATH);
- lastModified = mInputFile.lastModified();
- }
Toast.makeText(this, R.string.message_saving, Toast.LENGTH_SHORT).show();
// local save
LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND_NOTIFY, ".uno:Save", true));
}
- public void saveFilesToCloud(){
- final Activity activity = LibreOfficeMainActivity.this;
- final AsyncTask<Void, Void, Void> task = new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- try {
- // rebuild the IFile object from the data passed in the Intent
- IFile mStorageFile = DocumentProviderFactory.getInstance()
- .getProvider(providerId).createFromUri(LibreOfficeMainActivity.this, documentUri);
- // call document provider save operation
- mStorageFile.saveDocument(mInputFile);
- }
- catch (final RuntimeException e) {
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(activity, e.getMessage(),
- Toast.LENGTH_SHORT).show();
- }
- });
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- }
- return null;
+ /**
+ * Open file chooser and save the document to the URI
+ * selected there.
+ */
+ public void saveDocumentAs() {
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ String mimeType = getODFMimeTypeForDocument();
+ intent.setType(mimeType);
+ if (Build.VERSION.SDK_INT >= 26) {
+ intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, mDocumentUri);
+ }
+
+ startActivityForResult(intent, REQUEST_CODE_SAVEAS);
+ }
+
+ /**
+ * Saves the document under the given URI using ODF format
+ * and uses that URI from now on for all operations.
+ * @param newUri URI to save the document and use from now on.
+ */
+ private void saveDocumentAs(Uri newUri) {
+ mDocumentUri = newUri;
+ // save in ODF format
+ mTileProvider.saveDocumentAs(mTempFile.getPath(), true);
+ saveFileToOriginalSource();
+
+ String displayName = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), mDocumentUri);
+ toolbarTop.setTitle(displayName);
+ mbISReadOnlyMode = !isExperimentalMode();
+ getToolbarController().setupToolbars();
+ }
+
+ public void exportToPDF() {
+ Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType(FileUtilities.MIMETYPE_PDF);
+ // suggest directory and file name based on the doc
+ if (Build.VERSION.SDK_INT >= 26) {
+ intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, mDocumentUri);
+ }
+ final String displayName = toolbarTop.getTitle().toString();
+ final String suggestedFileName = FileUtilities.stripExtensionFromFileName(displayName) + ".pdf";
+ intent.putExtra(Intent.EXTRA_TITLE, suggestedFileName);
+
+ startActivityForResult(intent, REQUEST_CODE_EXPORT_TO_PDF);
+ }
+
+ private void exportToPDF(final Uri uri) {
+ boolean exportOK = false;
+ File tempFile = null;
+ try {
+ tempFile = File.createTempFile("LibreOffice_", ".pdf");
+ mTileProvider.saveDocumentAs(tempFile.getAbsolutePath(),"pdf", false);
+
+ try {
+ FileInputStream inputStream = new FileInputStream(tempFile);
+ exportOK = copyStreamToUri(inputStream, uri);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
}
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (tempFile != null && tempFile.exists()) {
+ tempFile.delete();
+ }
+ }
+
+ final int msgId = exportOK ? R.string.pdf_export_finished : R.string.unable_to_export_pdf;
+ LOKitShell.getMainHandler().post(new Runnable() {
@Override
- protected void onPostExecute(Void param) {
- Toast.makeText(activity, R.string.message_saved,
- Toast.LENGTH_SHORT).show();
- setDocumentChanged(false);
+ public void run() {
+ showCustomStatusMessage(getString(msgId));
}
- };
+ });
+ }
+
+ /**
+ * Returns the ODF MIME type that can be used for the current document,
+ * regardless of whether the document is an ODF Document or not
+ * (e.g. returns FileUtilities.MIMETYPE_OPENDOCUMENT_TEXT for a DOCX file).
+ * @return MIME type, or empty string, if no appropriate MIME type could be found.
+ */
+ private String getODFMimeTypeForDocument() {
+ if (mTileProvider.isTextDocument())
+ return FileUtilities.MIMETYPE_OPENDOCUMENT_TEXT;
+ else if (mTileProvider.isSpreadsheet())
+ return FileUtilities.MIMETYPE_OPENDOCUMENT_SPREADSHEET;
+ else if (mTileProvider.isPresentation())
+ return FileUtilities.MIMETYPE_OPENDOCUMENT_PRESENTATION;
+ else if (mTileProvider.isDrawing())
+ return FileUtilities.MIMETYPE_OPENDOCUMENT_GRAPHICS;
+ else {
+ Log.w(LOGTAG, "Cannot determine MIME type to use.");
+ return "";
+ }
+ }
- if (lastModified < mInputFile.lastModified()) {
- task.execute();
- lastModified = mInputFile.lastModified();
+ /**
+ * Returns whether the MIME type for the URI is considered one for a document template.
+ */
+ private boolean isTemplate(final Uri documentUri) {
+ final String mimeType = getContentResolver().getType(documentUri);
+ return FileUtilities.isTemplateMimeType(mimeType);
+ }
+
+ public void saveFileToOriginalSource() {
+ if (mTempFile == null || mDocumentUri == null || !mDocumentUri.getScheme().equals(ContentResolver.SCHEME_CONTENT))
+ return;
+
+ boolean copyOK = false;
+ try {
+ final FileInputStream inputStream = new FileInputStream(mTempFile);
+ copyOK = copyStreamToUri(inputStream, mDocumentUri);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (copyOK) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LibreOfficeMainActivity.this, R.string.message_saved,
+ Toast.LENGTH_SHORT).show();
+ }
+ });
+ setDocumentChanged(false);
} else {
- Toast.makeText(activity, R.string.message_save_incomplete, Toast.LENGTH_LONG).show();
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(LibreOfficeMainActivity.this, R.string.message_saving_failed,
+ Toast.LENGTH_SHORT).show();
+ }
+ });
}
}
@@ -412,28 +477,23 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
protected void onStart() {
Log.i(LOGTAG, "onStart..");
super.onStart();
- if (!isNewDocument){
- if (partIndex == -1)
- LOKitShell.sendLoadEvent(mInputFile.getPath());
- else
- LOKitShell.sendResumeEvent(mInputFile.getPath(), partIndex);
+ if (!mbSkipNextRefresh) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.REFRESH));
}
+ mbSkipNextRefresh = false;
}
@Override
protected void onStop() {
Log.i(LOGTAG, "onStop..");
- //save document to cache
- if (mTileProvider != null)
- mTileProvider.cacheDocument();
hideSoftKeyboardDirect();
- LOKitShell.sendCloseEvent();
super.onStop();
}
@Override
protected void onDestroy() {
Log.i(LOGTAG, "onDestroy..");
+ LOKitShell.sendCloseEvent();
mLayerClient.destroy();
super.onDestroy();
@@ -461,11 +521,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
public void onClick(DialogInterface dialog, int which) {
switch (which){
case DialogInterface.BUTTON_POSITIVE:
- if (isNewDocument) {
- saveAs();
- } else {
- mTileProvider.saveDocument();
- }
+ mTileProvider.saveDocument();
isDocumentChanged=false;
onBackPressed();
break;
@@ -802,7 +858,7 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
// this function can only be called in InvalidationHandler.java
public void setPassword() {
- mTileProvider.setDocumentPassword("file://"+mInputFile.getPath(), mPassword);
+ mTileProvider.setDocumentPassword("file://" + mTempFile.getPath(), mPassword);
}
// setTileProvider is meant to let main activity have a handle of LOKit when dealing with password
@@ -844,12 +900,12 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
});
}
- public void setIsSpreadsheet(boolean b) {
- mIsSpreadsheet = b;
+ public static boolean isReadOnlyMode() {
+ return mbISReadOnlyMode;
}
- public boolean isSpreadsheet() {
- return mIsSpreadsheet;
+ public boolean hasLocationForSave() {
+ return mDocumentUri != null;
}
public static void setDocumentChanged (boolean changed) {
@@ -860,7 +916,6 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
DocumentPartView partView = mDocumentPartViewListAdapter.getItem(position);
- partIndex = partView.partIndex;
LOKitShell.sendChangePartEvent(partView.partIndex);
mDrawerLayout.closeDrawer(mDrawerList);
}
@@ -923,12 +978,103 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
}
}
- // This method is used in LOKitTileProvider.java to show status of new file creation.
- public void showSaveStatusMessage(boolean error) {
- if (!error)
- Snackbar.make(mDrawerLayout, getString(R.string.create_new_file_success) + mInputFile.getName(), Snackbar.LENGTH_LONG).show();
- else
- Snackbar.make(mDrawerLayout, getString(R.string.create_new_file_error) + mInputFile.getName(), Snackbar.LENGTH_LONG).show(); }
+ /**
+ * Copies everything from the given input stream to the given output stream
+ * and closes both streams in the end.
+ * @return Whether copy operation was successful.
+ */
+ private boolean copyStream(InputStream inputStream, OutputStream outputStream) {
+ try {
+ byte[] buffer = new byte[4096];
+ int readBytes = inputStream.read(buffer);
+ while (readBytes != -1) {
+ outputStream.write(buffer, 0, readBytes);
+ readBytes = inputStream.read(buffer);
+ }
+ return true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ } finally {
+ try {
+ inputStream.close();
+ outputStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * Copies everything from the given Uri to the given OutputStream
+ * and closes the OutputStream in the end.
+ * The copy operation runs in a separate thread, but the method only returns
+ * after the thread has finished its execution.
+ * This can be used to copy in a blocking way when network access is involved,
+ * which is not allowed from the main thread, but that may happen when an underlying
+ * DocumentsProvider (like the NextCloud one) does network access.
+ */
+ private boolean copyUriToStream(final Uri inputUri, final OutputStream outputStream) {
+ class CopyThread extends Thread {
+ /** Whether copy operation was successful. */
+ private boolean result = false;
+
+ @Override
+ public void run() {
+ final ContentResolver contentResolver = getContentResolver();
+ try {
+ InputStream inputStream = contentResolver.openInputStream(inputUri);
+ result = copyStream(inputStream, outputStream);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ CopyThread copyThread = new CopyThread();
+ copyThread.start();
+ try {
+ // wait for copy operation to finish
+ // NOTE: might be useful to add some indicator in UI for long copy operations involving network...
+ copyThread.join();
+ } catch(InterruptedException e) {
+ e.printStackTrace();
+ }
+ return copyThread.result;
+ }
+
+ /**
+ * Copies everything from the given InputStream to the given URI and closes the
+ * InputStream in the end.
+ * @see LibreOfficeMainActivity#copyUriToStream(Uri, OutputStream)
+ * which does the same thing the other way around.
+ */
+ private boolean copyStreamToUri(final InputStream inputStream, final Uri outputUri) {
+ class CopyThread extends Thread {
+ /** Whether copy operation was successful. */
+ private boolean result = false;
+
+ @Override
+ public void run() {
+ final ContentResolver contentResolver = getContentResolver();
+ try {
+ OutputStream outputStream = contentResolver.openOutputStream(outputUri);
+ result = copyStream(inputStream, outputStream);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ CopyThread copyThread = new CopyThread();
+ copyThread.start();
+ try {
+ // wait for copy operation to finish
+ // NOTE: might be useful to add some indicator in UI for long copy operations involving network...
+ copyThread.join();
+ } catch(InterruptedException e) {
+ e.printStackTrace();
+ }
+ return copyThread.result;
+ }
public void showCustomStatusMessage(String message){
Snackbar.make(mDrawerLayout, message, Snackbar.LENGTH_LONG).show();
@@ -936,45 +1082,36 @@ public class LibreOfficeMainActivity extends AppCompatActivity implements Settin
public void preparePresentation() {
if (getExternalCacheDir() != null) {
- String tempPath = getExternalCacheDir().getPath() + "/" + mInputFile.getName() + ".svg";
+ String tempPath = getExternalCacheDir().getPath() + "/" + mTempFile.getName() + ".svg";
mTempSlideShowFile = new File(tempPath);
if (mTempSlideShowFile.exists() && !isDocumentChanged) {
startPresentation("file://" + tempPath);
} else {
- LOKitShell.sendSaveAsEvent(tempPath, "svg");
+ LOKitShell.sendSaveCopyAsEvent(tempPath, "svg");
}
}
}
public void startPresentation(String tempPath) {
- // pre-KitKat android doesn't have chrome-based WebView, which is needed to show svg slideshow
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- Intent intent = new Intent(this, PresentationActivity.class);
- intent.setData(Uri.parse(tempPath));
- startActivity(intent);
- } else {
- // copy the svg file path to clipboard for the user to paste in a browser
- ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
- ClipData clip = ClipData.newPlainText("temp svg file path", tempPath);
- clipboard.setPrimaryClip(clip);
-
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setMessage(R.string.alert_copy_svg_slide_show_to_clipboard)
- .setPositiveButton(R.string.alert_copy_svg_slide_show_to_clipboard_dismiss, null).show();
- }
+ Intent intent = new Intent(this, PresentationActivity.class);
+ intent.setData(Uri.parse(tempPath));
+ startActivity(intent);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- mFormattingController.handleActivityResult(requestCode, resultCode, data);
- hideBottomToolbar();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_CODE_SAVEAS && resultCode == RESULT_OK) {
+ final Uri fileUri = data.getData();
+ saveDocumentAs(fileUri);
+ } else if (requestCode == REQUEST_CODE_EXPORT_TO_PDF && resultCode == RESULT_OK) {
+ final Uri fileUri = data.getData();
+ exportToPDF(fileUri);
+ } else {
+ mFormattingController.handleActivityResult(requestCode, resultCode, data);
+ hideBottomToolbar();
+ }
}
-
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/LocaleHelper.java b/android/source/src/java/org/libreoffice/LocaleHelper.java
index 8c0e9b3fbbed..a87c63f09990 100644
--- a/android/source/src/java/org/libreoffice/LocaleHelper.java
+++ b/android/source/src/java/org/libreoffice/LocaleHelper.java
@@ -38,8 +38,7 @@ public class LocaleHelper {
Resources res = context.getResources();
Configuration cfg = res.getConfiguration();
cfg.locale = locale;
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1)
- cfg.setLayoutDirection(locale);
+ cfg.setLayoutDirection(locale);
res.updateConfiguration(cfg, res.getDisplayMetrics());
return context;
diff --git a/android/source/src/java/org/libreoffice/PasswordDialogFragment.java b/android/source/src/java/org/libreoffice/PasswordDialogFragment.java
index 112e35c4b7ed..08bc7f596894 100644
--- a/android/source/src/java/org/libreoffice/PasswordDialogFragment.java
+++ b/android/source/src/java/org/libreoffice/PasswordDialogFragment.java
@@ -4,9 +4,9 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.app.DialogFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
diff --git a/android/source/src/java/org/libreoffice/PresentationActivity.java b/android/source/src/java/org/libreoffice/PresentationActivity.java
index 3308e6884fe9..ede7c0c40101 100644
--- a/android/source/src/java/org/libreoffice/PresentationActivity.java
+++ b/android/source/src/java/org/libreoffice/PresentationActivity.java
@@ -1,16 +1,14 @@
package org.libreoffice;
import android.content.Intent;
-import android.os.Build;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.view.GestureDetectorCompat;
-import android.support.v7.app.AppCompatActivity;
+import androidx.annotation.Nullable;
+import androidx.core.view.GestureDetectorCompat;
+import androidx.appcompat.app.AppCompatActivity;
import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.view.WindowManager;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageButton;
@@ -25,19 +23,10 @@ public class PresentationActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // First we hide the status bar
- if (Build.VERSION.SDK_INT < 16) {
- // If the Android version is lower than Jellybean, use this call to hide
- // the status bar.
- getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
- WindowManager.LayoutParams.FLAG_FULLSCREEN);
- } else {
- // If higher than Jellybean
- View decorView = getWindow().getDecorView();
- // Hide the status bar.
- int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
- decorView.setSystemUiVisibility(uiOptions);
- }
+ View decorView = getWindow().getDecorView();
+ // Hide the status bar.
+ int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN;
+ decorView.setSystemUiVisibility(uiOptions);
setContentView(R.layout.presentation_mode);
@@ -185,4 +174,4 @@ public class PresentationActivity extends AppCompatActivity {
private void pageRight() {
mWebView.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT));
}
-} \ No newline at end of file
+}
diff --git a/android/source/src/java/org/libreoffice/SearchController.java b/android/source/src/java/org/libreoffice/SearchController.java
index a9414f7f7a71..6095e1fd2afe 100644
--- a/android/source/src/java/org/libreoffice/SearchController.java
+++ b/android/source/src/java/org/libreoffice/SearchController.java
@@ -11,7 +11,7 @@ import org.json.JSONException;
import org.json.JSONObject;
public class SearchController implements View.OnClickListener {
- private LibreOfficeMainActivity mActivity;
+ private final LibreOfficeMainActivity mActivity;
private enum SearchDirection {
UP, DOWN
@@ -69,15 +69,8 @@ public class SearchController implements View.OnClickListener {
ImageButton button = (ImageButton) view;
SearchDirection direction = SearchDirection.DOWN;
- switch(button.getId()) {
- case R.id.button_search_down:
- direction = SearchDirection.DOWN;
- break;
- case R.id.button_search_up:
- direction = SearchDirection.UP;
- break;
- default:
- break;
+ if (button.getId() == R.id.button_search_up) {
+ direction = SearchDirection.UP;
}
String searchText = ((EditText) mActivity.findViewById(R.id.search_string)).getText().toString();
diff --git a/android/source/src/java/org/libreoffice/ThumbnailCreator.java b/android/source/src/java/org/libreoffice/ThumbnailCreator.java
index 52870b67a5b9..c0c097747c69 100644
--- a/android/source/src/java/org/libreoffice/ThumbnailCreator.java
+++ b/android/source/src/java/org/libreoffice/ThumbnailCreator.java
@@ -71,7 +71,7 @@ public class ThumbnailCreator {
class ThumbnailCreationTask{
private final WeakReference<ImageView> imageViewReference;
- private int partNumber;
+ private final int partNumber;
private boolean cancelled = false;
public ThumbnailCreationTask(ImageView imageView, int partNumber) {
diff --git a/android/source/src/java/org/libreoffice/TileProvider.java b/android/source/src/java/org/libreoffice/TileProvider.java
index dabf30b834f7..c979a9883c13 100644
--- a/android/source/src/java/org/libreoffice/TileProvider.java
+++ b/android/source/src/java/org/libreoffice/TileProvider.java
@@ -22,9 +22,24 @@ import org.mozilla.gecko.gfx.IntSize;
public interface TileProvider {
/**
- * Save the current document.
+ * Save the current document under the given path.
+ * @param takeOwnership Whether to take ownership of the new file,
+ * i.e. whether the current document is changed to the
+ * newly saved document (takeOwnership = true),
+ * as compared to just saving a copy of the current document
+ * or exporting to a different file format.
+ * Must be 'false' when using this method for export to e.g. PNG or PDF.
+ * @return Whether saving was successful.
*/
- void saveDocumentAs(String filePath, String format);
+ boolean saveDocumentAs(String filePath, String format, boolean takeOwnership);
+
+ /**
+ * Saves the current document under the given path,
+ * using the default file format.
+ * @param takeOwnership (s. documentation for
+ * 'saveDocumentAs(String filePath, String format, boolean takeOwnership)')
+ */
+ boolean saveDocumentAs(String filePath, boolean takeOwnership);
/**
* Returns the page width in pixels.
@@ -72,6 +87,11 @@ public interface TileProvider {
void close();
/**
+ * Returns true if the current open document is a drawing.
+ */
+ boolean isDrawing();
+
+ /**
* Returns true if the current open document is a text document.
*/
boolean isTextDocument();
diff --git a/android/source/src/java/org/libreoffice/ToolbarController.java b/android/source/src/java/org/libreoffice/ToolbarController.java
index d21396cf4615..603d2258167e 100644
--- a/android/source/src/java/org/libreoffice/ToolbarController.java
+++ b/android/source/src/java/org/libreoffice/ToolbarController.java
@@ -11,7 +11,7 @@ package org.libreoffice;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
-import android.support.v7.widget.Toolbar;
+import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
@@ -45,12 +45,12 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
clipboardManager = (ClipboardManager)mContext.getSystemService(Context.CLIPBOARD_SERVICE);
}
- public void disableMenuItem(final int menuItemId, final boolean disabled) {
+ private void enableMenuItem(final int menuItemId, final boolean enabled) {
LOKitShell.getMainHandler().post(new Runnable() {
public void run() {
MenuItem menuItem = mMainMenu.findItem(menuItemId);
if (menuItem != null) {
- menuItem.setEnabled(!disabled);
+ menuItem.setEnabled(enabled);
} else {
Log.e(LOGTAG, "MenuItem not found.");
}
@@ -72,6 +72,8 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
void switchToEditMode() {
if (!LOKitShell.isEditingEnabled())
return;
+
+ setEditModeOn(true);
// Ensure the change is done on UI thread
LOKitShell.getMainHandler().post(new Runnable() {
@Override
@@ -89,7 +91,6 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
}
mToolbarTop.setNavigationIcon(R.drawable.ic_check);
mToolbarTop.setLogo(null);
- setEditModeOn(true);
}
});
}
@@ -145,7 +146,7 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
@Override
public void run() {
mMainMenu.setGroupVisible(R.id.group_edit_actions, false);
- mToolbarTop.setNavigationIcon(R.drawable.lo_icon);
+ mToolbarTop.setNavigationIcon(R.mipmap.ic_launcher);
mToolbarTop.setLogo(null);
setEditModeOn(false);
mContext.hideBottomToolbar();
@@ -161,94 +162,91 @@ public class ToolbarController implements Toolbar.OnMenuItemClickListener {
@Override
public boolean onMenuItemClick(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.action_keyboard:
- mContext.showSoftKeyboard();
- break;
- case R.id.action_format:
- mContext.showFormattingToolbar();
- break;
- case R.id.action_about:
- mContext.showAbout();
- return true;
- case R.id.action_save:
- if (mContext.isNewDocument) {
- mContext.saveAs();
- } else {
- mContext.getTileProvider().saveDocument();
- }
- return true;
- case R.id.action_parts:
- mContext.openDrawer();
- return true;
- case R.id.action_exportToPDF:
- mContext.getTileProvider().exportToPDF(false);
- return true;
- case R.id.action_print:
- mContext.getTileProvider().exportToPDF(true);
- return true;
- case R.id.action_settings:
- mContext.showSettings();
- return true;
- case R.id.action_search:
- mContext.showSearchToolbar();
- return true;
- case R.id.action_undo:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Undo"));
- return true;
- case R.id.action_redo:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Redo"));
- return true;
- case R.id.action_presentation:
- mContext.preparePresentation();
- return true;
- case R.id.action_add_slide:
- mContext.addPart();
- return true;
- case R.id.action_add_worksheet:
- mContext.addPart();
- return true;
- case R.id.action_rename_worksheet:
- case R.id.action_rename_slide:
- mContext.renamePart();
- return true;
- case R.id.action_delete_worksheet:
- mContext.deletePart();
- return true;
- case R.id.action_delete_slide:
- mContext.deletePart();
- return true;
- case R.id.action_back:
- hideClipboardActions();
- return true;
- case R.id.action_copy:
- LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Copy"));
- clipData = ClipData.newPlainText("clipboard data", clipboardText);
- clipboardManager.setPrimaryClip(clipData);
- Toast.makeText(mContext, mContext.getResources().getString(R.string.action_text_copied), Toast.LENGTH_SHORT).show();
- return true;
- case R.id.action_paste:
- clipData = clipboardManager.getPrimaryClip();
- ClipData.Item clipItem = clipData.getItemAt(0);
- mContext.setDocumentChanged(true);
- return mContext.getTileProvider().paste("text/plain;charset=utf-16", clipItem.getText().toString());
- case R.id.action_cut:
- clipData = ClipData.newPlainText("clipboard data", clipboardText);
- clipboardManager.setPrimaryClip(clipData);
- LOKitShell.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
- mContext.setDocumentChanged(true);
- return true;
- case R.id.action_UNO_commands:
- mContext.showUNOCommandsToolbar();
- return true;
+ final int itemId = item.getItemId();
+ if (itemId == R.id.action_keyboard) {
+ mContext.showSoftKeyboard();
+ } else if (itemId == R.id.action_format) {
+ mContext.showFormattingToolbar();
+ } else if (itemId == R.id.action_about) {
+ mContext.showAbout();
+ return true;
+ } else if (itemId == R.id.action_save) {
+ mContext.getTileProvider().saveDocument();
+ return true;
+ } else if (itemId == R.id.action_save_as) {
+ mContext.saveDocumentAs();
+ return true;
+ } else if (itemId == R.id.action_parts) {
+ mContext.openDrawer();
+ return true;
+ } else if (itemId == R.id.action_exportToPDF) {
+ mContext.exportToPDF();
+ return true;
+ } else if (itemId == R.id.action_print) {
+ mContext.getTileProvider().printDocument();
+ return true;
+ } else if (itemId == R.id.action_settings) {
+ mContext.showSettings();
+ return true;
+ } else if (itemId == R.id.action_search) {
+ mContext.showSearchToolbar();
+ return true;
+ } else if (itemId == R.id.action_undo) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Undo"));
+ return true;
+ } else if (itemId == R.id.action_redo) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Redo"));
+ return true;
+ } else if (itemId == R.id.action_presentation) {
+ mContext.preparePresentation();
+ return true;
+ } else if (itemId == R.id.action_add_slide || itemId == R.id.action_add_worksheet) {
+ mContext.addPart();
+ return true;
+ } else if (itemId == R.id.action_rename_worksheet || itemId == R.id.action_rename_slide) {
+ mContext.renamePart();
+ return true;
+ } else if (itemId == R.id.action_delete_worksheet || itemId == R.id.action_delete_slide) {
+ mContext.deletePart();
+ return true;
+ } else if (itemId == R.id.action_back) {
+ hideClipboardActions();
+ return true;
+ } else if (itemId == R.id.action_copy) {
+ LOKitShell.sendEvent(new LOEvent(LOEvent.UNO_COMMAND, ".uno:Copy"));
+ clipData = ClipData.newPlainText("clipboard data", clipboardText);
+ clipboardManager.setPrimaryClip(clipData);
+ Toast.makeText(mContext, mContext.getResources().getString(R.string.action_text_copied), Toast.LENGTH_SHORT).show();
+ return true;
+ } else if (itemId == R.id.action_paste) {
+ clipData = clipboardManager.getPrimaryClip();
+ ClipData.Item clipItem = clipData.getItemAt(0);
+ mContext.setDocumentChanged(true);
+ return mContext.getTileProvider().paste("text/plain;charset=utf-16", clipItem.getText().toString());
+ } else if (itemId == R.id.action_cut) {
+ clipData = ClipData.newPlainText("clipboard data", clipboardText);
+ clipboardManager.setPrimaryClip(clipData);
+ LOKitShell.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
+ mContext.setDocumentChanged(true);
+ return true;
+ } else if (itemId == R.id.action_UNO_commands) {
+ mContext.showUNOCommandsToolbar();
+ return true;
}
return false;
}
void setupToolbars() {
- if (mContext.usesTemporaryFile()) {
- disableMenuItem(R.id.action_save, true);
- Toast.makeText(mContext, mContext.getString(R.string.temp_file_saving_disabled), Toast.LENGTH_LONG).show();
+ if (LibreOfficeMainActivity.isExperimentalMode()) {
+ boolean enableSaveEntry = !LibreOfficeMainActivity.isReadOnlyMode() && mContext.hasLocationForSave();
+ enableMenuItem(R.id.action_save, enableSaveEntry);
+ if (LibreOfficeMainActivity.isReadOnlyMode()) {
+ // show message in case experimental mode is enabled (i.e. editing is supported in general),
+ // but current document is readonly
+ Toast.makeText(mContext, mContext.getString(R.string.readonly_file), Toast.LENGTH_LONG).show();
+ }
+ } else {
+ hideItem(R.id.action_save);
}
mMainMenu.findItem(R.id.action_parts).setVisible(mContext.isDrawerEnabled());
}
diff --git a/android/source/src/java/org/libreoffice/UNOCommandsController.java b/android/source/src/java/org/libreoffice/UNOCommandsController.java
index 9453b3bd07b7..cba67732cce1 100644
--- a/android/source/src/java/org/libreoffice/UNOCommandsController.java
+++ b/android/source/src/java/org/libreoffice/UNOCommandsController.java
@@ -8,7 +8,7 @@
package org.libreoffice;
import android.content.DialogInterface;
-import android.support.v7.app.AlertDialog;
+import androidx.appcompat.app.AlertDialog;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.EditText;
@@ -21,7 +21,7 @@ import org.json.JSONObject;
import static org.libreoffice.SearchController.addProperty;
class UNOCommandsController implements View.OnClickListener {
- private LibreOfficeMainActivity mActivity;
+ private final LibreOfficeMainActivity mActivity;
private JSONObject mRootJSON = new JSONObject();
@@ -72,7 +72,7 @@ class UNOCommandsController implements View.OnClickListener {
})
.setIcon(android.R.drawable.ic_dialog_info)
.show();
- TextView textView = (TextView) dialog.findViewById(android.R.id.message);
+ TextView textView = dialog.findViewById(android.R.id.message);
if (textView != null) {
textView.setScroller(new Scroller(mActivity));
textView.setVerticalScrollBarEnabled(true);
@@ -82,4 +82,4 @@ class UNOCommandsController implements View.OnClickListener {
e.printStackTrace();
}
}
-} \ No newline at end of file
+}
diff --git a/android/source/src/java/org/libreoffice/canvas/BitmapHandle.java b/android/source/src/java/org/libreoffice/canvas/BitmapHandle.java
index e46173db518f..51f6f7cf8611 100644
--- a/android/source/src/java/org/libreoffice/canvas/BitmapHandle.java
+++ b/android/source/src/java/org/libreoffice/canvas/BitmapHandle.java
@@ -5,7 +5,7 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
-import android.support.v4.content.ContextCompat;
+import androidx.core.content.ContextCompat;
/**
* Bitmap handle canvas element is used to show a handle on the screen.
diff --git a/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java b/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java
index c1f8e74e7ba2..a285234bc8b0 100644
--- a/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java
+++ b/android/source/src/java/org/libreoffice/canvas/CalcHeaderCell.java
@@ -4,29 +4,40 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
+import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextPaint;
public class CalcHeaderCell extends CommonCanvasElement {
- private TextPaint mTextPaint = new TextPaint();
- private Paint mBgPaint = new Paint();
- private RectF mBounds;
- private String mText;
+ private final TextPaint mTextPaint = new TextPaint();
+
+ private final Paint mFramePaint = new Paint();
+ private final Paint mBgPaint = new Paint();
+ private final RectF mBounds;
+ private final Rect mTextBounds = new Rect();
+ private final String mText;
public CalcHeaderCell(float left, float top, float width, float height, String text, boolean selected) {
mBounds = new RectF(left, top, left + width, top + height);
+
+ mFramePaint.setStyle(Style.STROKE);
+ mFramePaint.setColor(Color.BLACK);
+
+ mBgPaint.setStyle(Style.FILL);
+ mBgPaint.setColor(Color.GRAY);
+ // draw background more intensely when cell is selected
if (selected) {
- // if the cell is selected, display filled
- mBgPaint.setStyle(Style.FILL_AND_STROKE);
+ mBgPaint.setAlpha(100);
} else {
- // if not, display only the frame
- mBgPaint.setStyle(Style.STROKE);
+ mBgPaint.setAlpha(25);
}
- mBgPaint.setColor(Color.GRAY);
- mBgPaint.setAlpha(100); // hard coded for now
- mTextPaint.setColor(Color.GRAY);
+
+ mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextSize(24f); // hard coded for now
+ mTextPaint.setTextAlign(Paint.Align.CENTER);
mText = text;
+
+ mTextPaint.getTextBounds(mText, 0, mText.length(), mTextBounds);
}
/**
@@ -49,6 +60,7 @@ public class CalcHeaderCell extends CommonCanvasElement {
@Override
public void onDraw(Canvas canvas) {
canvas.drawRect(mBounds, mBgPaint);
- canvas.drawText(mText, mBounds.left, mBounds.bottom, mTextPaint);
+ canvas.drawRect(mBounds, mFramePaint);
+ canvas.drawText(mText, mBounds.centerX(), mBounds.centerY() - mTextBounds.centerY(), mTextPaint);
}
-} \ No newline at end of file
+}
diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java b/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
index 40c9ddcd8cea..8b99c292cbc5 100644
--- a/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
+++ b/android/source/src/java/org/libreoffice/overlay/CalcHeadersController.java
@@ -4,7 +4,7 @@ import android.content.Context;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
-import android.support.design.widget.Snackbar;
+import com.google.android.material.snackbar.Snackbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Gravity;
diff --git a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java b/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
index a8b2d2048409..98af7a9554e7 100644
--- a/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
+++ b/android/source/src/java/org/libreoffice/overlay/CalcHeadersView.java
@@ -4,7 +4,7 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.RectF;
-import android.support.v4.view.GestureDetectorCompat;
+import androidx.core.view.GestureDetectorCompat;
import android.util.AttributeSet;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
@@ -101,12 +101,8 @@ public class CalcHeadersView extends View {
bottom = -origin.y + zoom*mDimens.get(i);
if (top <= getHeight() && bottom >= 0) {
inRangeOfVisibleHeaders = true;
- if (mCellCursorRect != null && bottom > mCellCursorRect.top - origin.y && top < mCellCursorRect.bottom - origin.y) {
- // if cell is within current selected portion
- new CalcHeaderCell(0f, top, getWidth(), bottom - top, mLabels.get(i), true).onDraw(canvas);
- } else {
- new CalcHeaderCell(0f, top, getWidth(), bottom - top, mLabels.get(i), false).onDraw(canvas);
- }
+ boolean isSelected = mCellCursorRect != null && bottom > mCellCursorRect.top - origin.y && top < mCellCursorRect.bottom - origin.y;
+ new CalcHeaderCell(0f, top, getWidth(), bottom - top, mLabels.get(i), isSelected).onDraw(canvas);
} else {
if (inRangeOfVisibleHeaders) {
break;
@@ -116,12 +112,8 @@ public class CalcHeadersView extends View {
left = -origin.x + zoom*mDimens.get(i-1);
right = -origin.x + zoom*mDimens.get(i);
if (left <= getWidth() && right >= 0) {
- if (mCellCursorRect != null && right > mCellCursorRect.left - origin.x && left < mCellCursorRect.right - origin.x) {
- // if cell is within current selected portion
- new CalcHeaderCell(left, 0f, right - left, getHeight(), mLabels.get(i), true).onDraw(canvas);
- } else {
- new CalcHeaderCell(left, 0f, right - left, getHeight(), mLabels.get(i), false).onDraw(canvas);
- }
+ boolean isSelected = mCellCursorRect != null && right > mCellCursorRect.left - origin.x && left < mCellCursorRect.right - origin.x;
+ new CalcHeaderCell(left, 0f, right - left, getHeight(), mLabels.get(i), isSelected).onDraw(canvas);
} else {
if (inRangeOfVisibleHeaders) {
break;
diff --git a/android/source/src/java/org/libreoffice/storage/DocumentProviderFactory.java b/android/source/src/java/org/libreoffice/storage/DocumentProviderFactory.java
deleted file mode 100644
index acf5aebcd6c6..000000000000
--- a/android/source/src/java/org/libreoffice/storage/DocumentProviderFactory.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.libreoffice.storage.external.ExtsdDocumentsProvider;
-import org.libreoffice.storage.external.OTGDocumentsProvider;
-import org.libreoffice.storage.local.LocalDocumentsDirectoryProvider;
-import org.libreoffice.storage.local.LocalDocumentsProvider;
-import org.libreoffice.storage.owncloud.OwnCloudProvider;
-
-import android.content.Context;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-
-/**
- * Keeps the instances of the available IDocumentProviders in the system.
- * Instances are maintained in a sorted list and providers have to be
- * accessed from their position.
- *
- * The factory follows the Singleton pattern, there is only one instance of it
- * in the application and it must be retrieved with
- * DocumentProviderFactory.getInstance().
- */
-public final class DocumentProviderFactory {
- public static int EXTSD_PROVIDER_INDEX = 2;
- public static int OTG_PROVIDER_INDEX = 3;
-
- /**
- * Private factory instance for the Singleton pattern.
- */
- private static DocumentProviderFactory instance = null;
-
- private IDocumentProvider[] providers;
-
- private String[] providerNames;
-
- private DocumentProviderFactory() {
- // private to prevent external instances of the factory
- }
-
- /**
- * Initializes the factory with some context. If this method is called for
- * twice or more times those calls will have no effect.
- *
- * @param context
- * Application context for the factory.
- */
- public static void initialize(Context context) {
- if (instance == null) {
- // initialize instance
- instance = new DocumentProviderFactory();
-
- // initialize document providers list
- instance.providers = new IDocumentProvider[5];
- instance.providers[0] = new LocalDocumentsDirectoryProvider(0);
- instance.providers[1] = new LocalDocumentsProvider(1);
- instance.providers[OTG_PROVIDER_INDEX] = new OTGDocumentsProvider(OTG_PROVIDER_INDEX, context);
- instance.providers[4] = new OwnCloudProvider(4, context);
-
- instance.providers[EXTSD_PROVIDER_INDEX] = new ExtsdDocumentsProvider(EXTSD_PROVIDER_INDEX, context);
-
- // initialize document provider names list
- instance.providerNames = new String[instance.providers.length];
- for (int i = 0; i < instance.providers.length; i++) {
- instance.providerNames[i] = context.getString(instance
- .getProvider(i).getNameResource());
- }
- }
- }
-
- /**
- * Retrieve the unique instance of the factory.
- *
- * @return the unique factory object or null if it is not yet initialized.
- */
- public static DocumentProviderFactory getInstance() {
- return instance;
- }
-
- /**
- * Retrieve the provider associated to a certain id.
- *
- * @param id
- * @return document provider with that id.
- */
- public IDocumentProvider getProvider(int id) {
- // as for now, id == position in providers array
- return providers[id];
- }
-
- /**
- * Returns a sorted list of the names of the providers. Order is meaningful
- * to retrieve the actual provider object with getProvider().
- *
- * @return Array with the names of the available providers.
- */
- public String[] getNames() {
- return providerNames;
- }
-
- /**
- * Returns the default provider.
- *
- * @return default provider.
- */
- public IDocumentProvider getDefaultProvider() {
- return providers[0];
- }
-
- public Set<OnSharedPreferenceChangeListener> getChangeListeners() {
- Set<OnSharedPreferenceChangeListener> listeners =
- new HashSet<OnSharedPreferenceChangeListener>();
- for (IDocumentProvider provider : providers) {
- if (provider instanceof OnSharedPreferenceChangeListener)
- listeners.add((OnSharedPreferenceChangeListener) provider);
- }
- return listeners;
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java b/android/source/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
deleted file mode 100644
index b842e79fafd6..000000000000
--- a/android/source/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage;
-
-import java.util.Set;
-
-import org.libreoffice.R;
-import org.libreoffice.storage.external.BrowserSelectorActivity;
-
-import android.content.Intent;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceFragment;
-import android.preference.PreferenceManager;
-import android.preference.PreferenceScreen;
-import android.support.v7.app.AppCompatActivity;
-
-public class DocumentProviderSettingsActivity extends AppCompatActivity {
-
- public static final String KEY_PREF_OWNCLOUD_SERVER = "pref_server_url";
- public static final String KEY_PREF_OWNCLOUD_USER_NAME = "pref_user_name";
- public static final String KEY_PREF_OWNCLOUD_PASSWORD = "pref_password";
- public static final String KEY_PREF_EXTERNAL_SD_PATH_URI = "pref_extsd_path_uri";
- public static final String KEY_PREF_OTG_PATH_URI = "pref_otg_path_uri";
-
- private Set<OnSharedPreferenceChangeListener> listeners;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Display the fragment as the main content.
- getFragmentManager().beginTransaction()
- .replace(android.R.id.content, new SettingsFragment()).commit();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- listeners = DocumentProviderFactory.getInstance().getChangeListeners();
- for (OnSharedPreferenceChangeListener listener : listeners) {
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(listener);
- }
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- for (OnSharedPreferenceChangeListener listener : listeners) {
- PreferenceManager.getDefaultSharedPreferences(this)
- .unregisterOnSharedPreferenceChangeListener(listener);
- }
- }
-
- public static class SettingsFragment extends PreferenceFragment {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // Load the preferences from an XML resource
- addPreferencesFromResource(R.xml.documentprovider_preferences);
-
- PreferenceScreen extSDPreference =
- (PreferenceScreen)findPreference(KEY_PREF_EXTERNAL_SD_PATH_URI);
- PreferenceScreen otgPreference =
- (PreferenceScreen)findPreference(KEY_PREF_OTG_PATH_URI);
-
- extSDPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- startBrowserSelectorActivity(KEY_PREF_EXTERNAL_SD_PATH_URI,
- BrowserSelectorActivity.MODE_EXT_SD);
- return true;
- }
- });
- otgPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- startBrowserSelectorActivity(KEY_PREF_OTG_PATH_URI,
- BrowserSelectorActivity.MODE_OTG);
- return true;
- }
- });
-
- }
-
- private void startBrowserSelectorActivity(String prefKey, String mode) {
- Intent i = new Intent(getActivity(), BrowserSelectorActivity.class);
- i.putExtra(BrowserSelectorActivity.PREFERENCE_KEY_EXTRA, prefKey);
- i.putExtra(BrowserSelectorActivity.MODE_EXTRA, mode);
- startActivity(i);
- }
-
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/IDocumentProvider.java b/android/source/src/java/org/libreoffice/storage/IDocumentProvider.java
deleted file mode 100644
index 044d7ddb422b..000000000000
--- a/android/source/src/java/org/libreoffice/storage/IDocumentProvider.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage;
-
-import android.content.Context;
-
-import java.net.URI;
-
-/**
- * Represents a Document Provider, an object able to provide documents from a
- * certain source (e.g. local documents, DropBox, Google Docs).
- */
-public interface IDocumentProvider {
-
- /**
- * Provides the content root element for the Document Provider.
- *
- * @return Content root element.
- * @throws RuntimeException in case of error.
- * @param context
- */
- IFile getRootDirectory(Context context);
-
- /**
- * Transforms some URI into the IFile object that represents that content.
- *
- *
- * @param context
- * @param uri
- * URI pointing to some content object that has been previously
- * retrieved with IFile.getUri().
- * @return IFile object pointing to the content represented by uri.
- * @throws RuntimeException in case of error.
- */
- IFile createFromUri(Context context, URI uri);
-
- /**
- * Get internationalized name for this provider. This name is intended to be
- * shown in the UI.
- *
- * @return string resource pointing to the provider name.
- */
- int getNameResource();
-
- /**
- * Provides the unique ID for a document provider instance in a program.
- *
- * This ID should be set when the instance is built. It could be used to
- * tell two instances of the same document provider apart, e. g. two
- * instances of OwnCloudProvider pointing to different servers.
- *
- * @return Unique ID for a document provider instance.
- */
- int getId();
-
- /**
- * Checks if the Document Provider is available or not.
- *
- * @return A boolean value based on provider availability.
- * @param context
- */
- boolean checkProviderAvailability(Context context);
-}
diff --git a/android/source/src/java/org/libreoffice/storage/IFile.java b/android/source/src/java/org/libreoffice/storage/IFile.java
deleted file mode 100644
index c9cfa7f1198d..000000000000
--- a/android/source/src/java/org/libreoffice/storage/IFile.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage;
-
-import android.content.Context;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.net.URI;
-import java.util.Date;
-import java.util.List;
-
-/**
- * An abstraction of the File class, intended to be implemented by different
- * Document Providers.
- *
- * It represents a file or a directory in the context of a certain Document
- * Provider. It wraps the file-related operations and provides access to the
- * final document as a local File, downloading it if necessary.
- */
-public interface IFile {
-
- /**
- * Provides a URI that represents this IFile object.
- *
- * @return URI that represents this IFile object in the context of the
- * Document Provider that created it. The URI can be transformed
- * back into an IFile object with IDocumentProvider.createFromUri().
- */
- URI getUri();
-
- /**
- * Returns the name of the file or directory represented by this file.
- *
- * @return This file's name.
- */
- String getName();
-
- /**
- * Indicates if this file represents a directory in the context of the
- * Document Provider which originated it.
- *
- * @return true if this file is a directory, false otherwise.
- */
- boolean isDirectory();
-
- /**
- * Returns the file size in bytes.
- *
- * @return file size in bytes, 0 if the file does not exist.
- */
- long getSize();
-
- /**
- * Returns the time when this file was last modified, measured in
- * milliseconds since January 1st, 1970, midnight.
- *
- * @return time when this file was last modified, or 0 if the file does not
- * exist.
- */
- Date getLastModified();
-
- /**
- * Returns a list containing the files in the directory represented by this
- * file.
- *
- * @return list of files contained by this directory, or an empty list if
- * this is not a directory.
- * @throws RuntimeException in case of error.
- */
- List<IFile> listFiles();
-
- /**
- * Gets the list of files contained in the directory represented by this
- * file, and filters it through some FilenameFilter.
- *
- * @param filter
- * the filter to match names against.
- * @return filtered list of files contained by this directory, or an empty
- * list if this is not a directory.
- * @throws RuntimeException in case of error.
- */
- List<IFile> listFiles(FileFilter filter);
-
- /**
- * Returns the pparent of this file.
- *
- * @return this file's parent or null if it does not have it.
- * @param context
- */
- IFile getParent(Context context);
-
- /**
- * Returns the document wrapped by this IFile as a local file. The result
- * for a directory is not defined.
- *
- * @return local file containing the document wrapped by this object.
- * @throws RuntimeException in case of error.
- */
- File getDocument();
-
- /**
- * Replaces the wrapped document with a new version of it.
- *
- * @param file
- * A local file pointing to the new version of the document.
- */
- void saveDocument(File file);
-}
diff --git a/android/source/src/java/org/libreoffice/storage/IOUtils.java b/android/source/src/java/org/libreoffice/storage/IOUtils.java
deleted file mode 100644
index f345f5cbed3b..000000000000
--- a/android/source/src/java/org/libreoffice/storage/IOUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.libreoffice.storage;
-
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * File IO related methods.
- */
-public class IOUtils {
- private static final int BUFFER_SIZE = 1024 * 8;
- private static final String LOGTAG = IOUtils.class.getSimpleName();
-
- public static File getFileFromURIString(String URIpath) throws IllegalArgumentException{
- try{
- return new File(new URI(URIpath));
- } catch (URISyntaxException e) {
- //should not happen as all URIs are system generated
- Log.wtf(LOGTAG, e.getReason());
- return null;
- }
- }
-
- public static boolean isInvalidFile(File f) {
- return f == null || !f.exists() || f.getTotalSpace() == 0
- || !f.canRead() || !f.canWrite();
- }
-
- public static int copy(InputStream input, OutputStream output) throws Exception {
- byte[] buffer = new byte[BUFFER_SIZE];
-
- BufferedInputStream in = new BufferedInputStream(input, BUFFER_SIZE);
- BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
-
- int count = 0, n = 0;
- try {
- while ((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
- out.write(buffer, 0, n);
- count += n;
- }
- out.flush();
- } finally {
- if (out != null) out.close();
- if (in != null) in.close();
- }
-
- return count;
- }
-
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/BrowserSelectorActivity.java b/android/source/src/java/org/libreoffice/storage/external/BrowserSelectorActivity.java
deleted file mode 100644
index 07b64623b701..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/BrowserSelectorActivity.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.libreoffice.storage.external;
-
-import android.annotation.TargetApi;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.content.UriPermission;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.preference.PreferenceManager;
-import android.support.v7.app.AppCompatActivity;
-import android.util.Log;
-
-import org.libreoffice.R;
-import org.libreoffice.storage.DocumentProviderFactory;
-
-import java.util.Set;
-
-/**
- * Activity to select which directory browser to use.
- * Android 5+ will use the DocumentTree intent to locate a browser.
- * Android 4+ & OTG will use the internal directory browser.
- */
-public class BrowserSelectorActivity extends AppCompatActivity {
- public static final String PREFERENCE_KEY_EXTRA = "org.libreoffice.pref_key_extra";
- public static final String MODE_EXTRA = "org.libreoffice.mode_extra";
- public static final String MODE_OTG = "OTG";
- public static final String MODE_EXT_SD = "EXT_SD";
-
- private static final String LOGTAG = BrowserSelectorActivity.class.getSimpleName();
- private static final int REQUEST_DOCUMENT_TREE = 1;
- private static final int REQUEST_INTERNAL_BROWSER = 2;
- private Set<SharedPreferences.OnSharedPreferenceChangeListener> listeners;
- private String preferenceKey;
- private SharedPreferences preferences;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- preferenceKey = getIntent().getStringExtra(PREFERENCE_KEY_EXTRA);
- preferences = PreferenceManager.getDefaultSharedPreferences(this);
- String mode = getIntent().getStringExtra(MODE_EXTRA);
-
- if(mode.equals(MODE_EXT_SD)) {
- findSDCard();
- } else if (mode.equals(MODE_OTG)) {
- findOTGDevice();
- }
- }
-
- private void findOTGDevice() {
- useInternalBrowser(DocumentProviderFactory.OTG_PROVIDER_INDEX);
- }
-
- private void findSDCard() {
- if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- useDocumentTreeBrowser();
- } else {
- useInternalBrowser(DocumentProviderFactory.EXTSD_PROVIDER_INDEX);
- }
- }
-
- private void useInternalBrowser(int providerIndex) {
- IExternalDocumentProvider provider =
- (IExternalDocumentProvider) DocumentProviderFactory.getInstance()
- .getProvider(providerIndex);
- String previousDirectoryPath = preferences.getString(preferenceKey, provider.guessRootURI(this));
- Intent i = new Intent(this, DirectoryBrowserActivity.class);
- i.putExtra(DirectoryBrowserActivity.DIRECTORY_PATH_EXTRA, previousDirectoryPath);
- startActivityForResult(i, REQUEST_INTERNAL_BROWSER);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void useDocumentTreeBrowser() {
- Intent i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
- startActivityForResult(i, REQUEST_DOCUMENT_TREE);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- //listeners are registered here as onActivityResult is called before onResume
- super.onActivityResult(requestCode, resultCode, data);
-
- registerListeners();
- if(resultCode == RESULT_OK) {
- switch(requestCode) {
- case REQUEST_DOCUMENT_TREE:
- Uri treeUri = data.getData();
- preferences.edit()
- .putString(preferenceKey, treeUri.toString())
- .apply();
-
- updatePersistedUriPermission(treeUri);
- getContentResolver().takePersistableUriPermission(treeUri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION |
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- break;
-
- case REQUEST_INTERNAL_BROWSER:
- Uri fileUri = data.getData();
- preferences.edit()
- .putString(preferenceKey, fileUri.toString())
- .apply();
- break;
- default:
- }
- }
- unregisterListeners();
- Log.d(LOGTAG, "Preference saved: " +
- preferences.getString(preferenceKey, getString(R.string.directory_not_saved)));
- finish();
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void updatePersistedUriPermission(Uri treeUri) {
- freePreviousUriPermissions();
-
- //TODO: Use non-emulator Android 5+ device to check if needed
- /*this.grantUriPermission(this.getPackageName(),
- treeUri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION |
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION); */
-
- getContentResolver().takePersistableUriPermission(treeUri,
- Intent.FLAG_GRANT_READ_URI_PERMISSION |
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void freePreviousUriPermissions() {
- ContentResolver cr = getContentResolver();
- for (UriPermission uriPermission : cr.getPersistedUriPermissions()) {
- cr.releasePersistableUriPermission(uriPermission.getUri(), 0);
- }
- }
-
- private void registerListeners() {
- listeners = DocumentProviderFactory.getInstance().getChangeListeners();
- for (SharedPreferences.OnSharedPreferenceChangeListener listener : listeners) {
- PreferenceManager.getDefaultSharedPreferences(this)
- .registerOnSharedPreferenceChangeListener(listener);
- }
- }
-
- private void unregisterListeners() {
- for (SharedPreferences.OnSharedPreferenceChangeListener listener : listeners) {
- PreferenceManager.getDefaultSharedPreferences(this)
- .unregisterOnSharedPreferenceChangeListener(listener);
- }
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserActivity.java b/android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserActivity.java
deleted file mode 100644
index 1cf9f52fa7c0..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserActivity.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.libreoffice.storage.external;
-
-
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v7.app.AppCompatActivity;
-
-import org.libreoffice.R;
-
-/**
- * Container for DirectoryBrowserFragment
- */
-public class DirectoryBrowserActivity extends AppCompatActivity {
- public static final String DIRECTORY_PATH_EXTRA = "org.libreoffice.directory_path_extra";
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Intent data = getIntent();
- String initialPath = data.getStringExtra(DIRECTORY_PATH_EXTRA);
-
- setContentView(R.layout.activity_directory_browser);
- FragmentManager fm = getFragmentManager();
- Fragment fragment = DirectoryBrowserFragment.newInstance(initialPath);
- fm.beginTransaction()
- .add(R.id.fragment_container, fragment)
- .commit();
- }
-
- @Override
- public void onBackPressed() {
- FragmentManager fm = getFragmentManager();
- if(fm.getBackStackEntryCount() > 0) {
- fm.popBackStack();
- } else {
- super.onBackPressed();
- }
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserFragment.java b/android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserFragment.java
deleted file mode 100644
index 18165650a617..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/DirectoryBrowserFragment.java
+++ /dev/null
@@ -1,199 +0,0 @@
-package org.libreoffice.storage.external;
-
-import android.app.Activity;
-import android.app.Fragment;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Environment;
-import android.support.annotation.Nullable;
-import android.util.Log;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import org.libreoffice.R;
-import org.libreoffice.storage.IOUtils;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Comparator;
-
-/**
- * A simple directory browser.
- */
-public class DirectoryBrowserFragment extends Fragment {
- private static final String LOGTAG = DirectoryBrowserFragment.class.getSimpleName();
- private static final String INITIAL_PATH_URI_KEY = "initial_path";
- private File currentDirectory;
- private FileArrayAdapter directoryAdapter;
-
- public static DirectoryBrowserFragment newInstance(String initialPathURI) {
- Bundle args = new Bundle();
- args.putString(INITIAL_PATH_URI_KEY, initialPathURI);
- DirectoryBrowserFragment fragment = new DirectoryBrowserFragment();
- fragment.setArguments(args);
- Log.d(LOGTAG, "Saved path: " + initialPathURI);
-
- return fragment;
- }
-
- @Override
- public void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- String initialPathURI = getArguments().getString(INITIAL_PATH_URI_KEY);
- setupCurrentDirectory(initialPathURI);
- }
-
- @Nullable
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View v = inflater.inflate(R.layout.fragment_directory_browser, container, false);
-
- final EditText directoryHeader = v.findViewById(R.id.directory_header);
- Button directorySearchButton = v.findViewById(R.id.directory_search_button);
- Button positiveButton = v.findViewById(R.id.confirm_button);
- Button negativeButton = v.findViewById(R.id.cancel_button);
- ImageView upImage = v.findViewById(R.id.up_image);
- ListView directoryListView = v.findViewById(R.id.directory_list);
-
- directoryHeader.setText(currentDirectory.getPath());
- directorySearchButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String currentPath = currentDirectory.getAbsolutePath();
- String enteredPath = directoryHeader.getText().toString();
- File testDirectory = new File(enteredPath);
- if(enteredPath.equals(currentPath)) ;
- else if (isInvalidFileDirectory(testDirectory)) {
- Toast.makeText(getActivity(), R.string.bad_directory, Toast.LENGTH_SHORT)
- .show();
- }
- else {
- changeDirectory(testDirectory);
- }
- }
- });
-
- positiveButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- Intent data = new Intent();
- data.setData(Uri.fromFile(currentDirectory));
- getActivity().setResult(Activity.RESULT_OK, data);
- getActivity().finish();
- }
- });
-
- negativeButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- getActivity().setResult(Activity.RESULT_CANCELED, null);
- getActivity().finish();
- }
- });
-
- upImage.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- changeDirectory(currentDirectory.getParentFile());
- }
- });
-
- directoryAdapter = new FileArrayAdapter(getActivity(), new ArrayList<File>());
- directoryAdapter.populateFileList(currentDirectory);
- directoryListView.setAdapter(directoryAdapter);
- directoryListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- changeDirectory(directoryAdapter.getItem(position));
- }
- });
-
- return v;
- }
-
- private void changeDirectory(File destination) {
- if(destination == null) {
- Toast.makeText(getActivity(), R.string.unable_to_go_further, Toast.LENGTH_SHORT)
- .show();
- } else {
- Fragment fragment = DirectoryBrowserFragment.newInstance(destination.toURI().toString());
- getActivity().getFragmentManager().beginTransaction()
- .replace(R.id.fragment_container, fragment)
- .addToBackStack(null)
- .commit();
- }
- }
-
- private void setupCurrentDirectory(String initialPathURI) {
- File initialDirectory = null;
- if(initialPathURI != null && !initialPathURI.isEmpty()) {
- initialDirectory = IOUtils.getFileFromURIString(initialPathURI);
- }
-
- if(isInvalidFileDirectory(initialDirectory)) {
- initialDirectory = Environment.getExternalStorageDirectory();
- }
- currentDirectory = initialDirectory;
- }
-
- private boolean isInvalidFileDirectory(File f) {
- return f == null || !f.exists() || !f.isDirectory() ||!f.canRead();
- }
-
- private class FileArrayAdapter extends ArrayAdapter<File> {
- private Comparator<File> caseInsensitiveNaturalOrderComparator;
-
- public FileArrayAdapter(Context context, ArrayList<File> files) {
- super(context, 0, files);
- caseInsensitiveNaturalOrderComparator = new AlphabeticalFileComparator();
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getActivity().getLayoutInflater()
- .inflate(android.R.layout.simple_list_item_1, null);
- }
-
- File f = this.getItem(position);
- TextView tv = convertView.findViewById(android.R.id.text1);
- tv.setText(f.getName());
-
- return convertView;
- }
-
- public void sortAlphabetically() {
- this.sort(caseInsensitiveNaturalOrderComparator);
- }
-
- public void populateFileList(File directory) {
- for(File f : directory.listFiles()){
- if(f.isDirectory()){
- directoryAdapter.add(f);
- }
- }
- directoryAdapter.sortAlphabetically();
- }
- }
-
- private class AlphabeticalFileComparator implements Comparator<File> {
- @Override
- public int compare(File lhs, File rhs) {
- String lhsName = lhs.getName();
- String rhsName = rhs.getName();
-
- return lhsName.compareToIgnoreCase(rhsName);
- }
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/ExternalFile.java b/android/source/src/java/org/libreoffice/storage/external/ExternalFile.java
deleted file mode 100644
index aff33e4413ef..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/ExternalFile.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package org.libreoffice.storage.external;
-
-import android.content.Context;
-import android.support.v4.provider.DocumentFile;
-import android.util.Log;
-
-import org.libreoffice.storage.IFile;
-import org.libreoffice.storage.IOUtils;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Implementation of IFile for the external file system, for Android 4.4+
- *
- * Uses the DocumentFile class.
- *
- * The DocumentFile class obfuscates the path of the files it wraps,
- * preventing usage of LOK's documentLoad method. A copy of the DocumentFile's contents
- * will be created in the cache when files are opened, allowing use of documentLoad.
- */
-public class ExternalFile implements IFile{
- private final static String LOGTAG = "ExternalFile";
-
- private ExtsdDocumentsProvider provider;
- private DocumentFile docFile;
- private File duplicateFile;
- private Context context;
-
- public ExternalFile(ExtsdDocumentsProvider provider, DocumentFile docFile, Context context) {
- this.provider = provider;
- this.context = context;
- this.docFile = docFile;
- }
-
- @Override
- public URI getUri() {
- try{
- return new URI(docFile.toString());
- } catch (URISyntaxException e) {
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- return null;
- }
- }
-
- @Override
- public String getName() {
- return docFile.getName();
- }
-
- @Override
- public boolean isDirectory() {
- return docFile.isDirectory();
- }
-
- @Override
- public long getSize() {
- return docFile.length();
- }
-
- @Override
- public Date getLastModified() {
- return new Date(docFile.lastModified());
- }
-
- @Override
- public List<IFile> listFiles() {
- List<IFile> children = new ArrayList<IFile>();
- for (DocumentFile child : docFile.listFiles()) {
- children.add(new ExternalFile(provider, child, context));
- }
- return children;
- }
-
- @Override
- public List<IFile> listFiles(FileFilter filter) {
- File file;
- try{
- List<IFile> children = new ArrayList<IFile>();
- for (DocumentFile child : docFile.listFiles()) {
- file = new File(new URI(child.getUri().toString()));
- if(filter.accept(file))
- children.add(new ExternalFile(provider, child, context));
- }
- return children;
-
- }catch (Exception e){
- e.printStackTrace();
- }
- /* if something goes wrong */
- return listFiles();
-
- }
-
- @Override
- public IFile getParent(Context context) {
- // this is the root node
- if(docFile.getParentFile() == null) return null;
-
- return new ExternalFile(provider, docFile.getParentFile(), this.context);
- }
-
- @Override
- public File getDocument() {
- if(isDirectory()) {
- return null;
- } else {
- duplicateFile = duplicateInCache();
- return duplicateFile;
- }
- }
-
- private File duplicateInCache() {
- try{
- InputStream istream = context.getContentResolver().
- openInputStream(docFile.getUri());
-
- File storageFolder = provider.getCacheDir();
- File fileCopy = new File(storageFolder, docFile.getName());
- OutputStream ostream = new FileOutputStream(fileCopy);
-
- IOUtils.copy(istream, ostream);
- return fileCopy;
- } catch (Exception e) {
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- return null;
- }
- }
-
- @Override
- public void saveDocument(File file) {
- try{
- OutputStream ostream = context.getContentResolver().
- openOutputStream(docFile.getUri());
- InputStream istream = new FileInputStream(file);
-
- IOUtils.copy(istream, ostream);
-
- } catch (Exception e) {
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- }
- }
-
- @Override
- public boolean equals(Object object) {
- if (this == object)
- return true;
- if (!(object instanceof ExternalFile))
- return false;
- ExternalFile file = (ExternalFile) object;
- return file.getUri().equals(getUri());
- }
-
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/ExtsdDocumentsProvider.java b/android/source/src/java/org/libreoffice/storage/external/ExtsdDocumentsProvider.java
deleted file mode 100644
index e45929374bbd..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/ExtsdDocumentsProvider.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.libreoffice.storage.external;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.content.pm.PackageManager;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.preference.PreferenceManager;
-import android.support.v4.content.ContextCompat;
-import android.support.v4.provider.DocumentFile;
-import android.util.Log;
-
-import org.libreoffice.R;
-import org.libreoffice.storage.DocumentProviderSettingsActivity;
-import org.libreoffice.storage.IFile;
-
-import java.io.File;
-import java.net.URI;
-
-/**
- * Implementation of IDocumentProvider for the external file system, for android 4.4+
- *
- * The DocumentFile class is required when accessing files in external storage
- * for Android 4.4+. The ExternalFile class is used to handle this.
- *
- * Android 4.4 & 5+ use different types of root directory paths,
- * 5 using a DirectoryTree Uri and 4.4 using a normal File path.
- * As such, different methods are required to obtain the rootDirectory IFile.
- * 4.4 has to guess the location of the rootDirectory as well.
- */
-public class ExtsdDocumentsProvider implements IExternalDocumentProvider,
- OnSharedPreferenceChangeListener{
- private static final String LOGTAG = ExtsdDocumentsProvider.class.getSimpleName();
-
- private int id;
- private File cacheDir;
- private String rootPathURI;
-
- public ExtsdDocumentsProvider(int id, Context context) {
- this.id = id;
- setupRootPathUri(context);
- setupCache(context);
- }
-
- private void setupRootPathUri(Context context) {
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
- rootPathURI = preferences.getString(
- DocumentProviderSettingsActivity.KEY_PREF_EXTERNAL_SD_PATH_URI, guessRootURI(context));
- }
-
- public String guessRootURI(Context context) {
- // TODO: unfortunately the getExternalFilesDirs function relies on devices to actually
- // follow guidelines re external storage. Of course device manufacturers don't and as such
- // you cannot rely on it returning the actual paths (neither the compat, nor the native variant)
- File[] possibleRemovables = ContextCompat.getExternalFilesDirs(context,null);
- // the primary dir that is already covered by the "LocalDocumentsProvider"
- // might be emulated/part of internal memory or actual SD card
- // TODO: change to not confuse android's "external storage" with "expandable storage"
- String primaryExternal = Environment.getExternalStorageDirectory().getAbsolutePath();
-
- for (File option: possibleRemovables) {
- // Returned paths may be null if a storage device is unavailable.
- if (null == option) {
- Log.w(LOGTAG,"path was a null option :-/"); continue; }
- String optionPath = option.getAbsolutePath();
- if(optionPath.contains(primaryExternal)) {
- Log.v(LOGTAG, "did get file path - but is same as primary storage ("+ primaryExternal +")");
- continue;
- }
-
- return option.toURI().toString();
- }
-
- // TODO: do some manual probing of possible directories (/storage/sdcard1 and similar)
- Log.i(LOGTAG, "no secondary storage reported");
- return null;
- }
-
- private void setupCache(Context context) {
- // TODO: probably we should do smarter cache management
- cacheDir = new File(context.getExternalCacheDir(), "externalFiles");
- if (cacheDir.exists()) {
- deleteRecursive(cacheDir);
- }
- cacheDir.mkdirs();
- }
-
- private static void deleteRecursive(File file) {
- if (file.isDirectory()) {
- for (File child : file.listFiles())
- deleteRecursive(child);
- }
- file.delete();
- }
-
- public File getCacheDir() {
- return cacheDir;
- }
-
- @Override
- public IFile getRootDirectory(Context context) {
- if(android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
- return android4RootDirectory(context);
- } else {
- return android5RootDirectory(context);
- }
- }
-
- private ExternalFile android4RootDirectory(Context context) {
- try{
- File f = new File(new URI(rootPathURI));
- return new ExternalFile(this, DocumentFile.fromFile(f), context);
- } catch (Exception e) {
- //invalid rootPathURI
- throw buildRuntimeExceptionForInvalidFileURI(context);
- }
- }
-
- private ExternalFile android5RootDirectory(Context context) {
- try {
- return new ExternalFile(this,
- DocumentFile.fromTreeUri(context, Uri.parse(rootPathURI)),
- context);
- } catch (Exception e) {
- //invalid rootPathURI
- throw buildRuntimeExceptionForInvalidFileURI(context);
- }
- }
-
- private RuntimeException buildRuntimeExceptionForInvalidFileURI(Context context) {
- // ToDo: discarding the original exception / catch-all handling is bad style
- return new RuntimeException(context.getString(R.string.ext_document_provider_error));
- }
-
- @Override
- public IFile createFromUri(Context context, URI javaURI) {
- //TODO: refactor when new DocumentFile API exist
- //uri must be of a DocumentFile file, not directory.
- Uri androidUri = Uri.parse(javaURI.toString());
- return new ExternalFile(this,
- DocumentFile.fromSingleUri(context, androidUri),
- context);
- }
-
- @Override
- public int getNameResource() {
- return R.string.external_sd_file_system;
- }
-
- @Override
- public int getId() {
- return id;
- }
-
- @Override
- public boolean checkProviderAvailability(Context context) {
- // too many devices (or I am just unlucky) don't report the mounted state properly, and other
- // devices also consider dedicated part of internal storage to be "mounted" so cannot use
- // getExternalStorageState().equals(Environment.MEDIA_MOUNTED) && isExternalStorageRemovable()
- // but they refer to the primary external storage anyway, so what currently is covered by the
- // "LocalDocumentsProvider"
- return rootPathURI!=null && ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
- if (key.equals(DocumentProviderSettingsActivity.KEY_PREF_EXTERNAL_SD_PATH_URI)) {
- rootPathURI = preferences.getString(key, "");
- }
- }
-
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/IExternalDocumentProvider.java b/android/source/src/java/org/libreoffice/storage/external/IExternalDocumentProvider.java
deleted file mode 100644
index a439417b60cd..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/IExternalDocumentProvider.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.libreoffice.storage.external;
-
-import android.content.Context;
-
-import org.libreoffice.storage.IDocumentProvider;
-
-
-/**
- * Interface for external document providers.
- */
-public interface IExternalDocumentProvider extends IDocumentProvider {
-
- /**
- * Used to obtain the default directory to display when
- * browsing using the internal DirectoryBrowser.
- *
- * @return a guess of the root file's URI.
- * @param context
- */
- String guessRootURI(Context context);
-
-}
diff --git a/android/source/src/java/org/libreoffice/storage/external/OTGDocumentsProvider.java b/android/source/src/java/org/libreoffice/storage/external/OTGDocumentsProvider.java
deleted file mode 100644
index 4341bc3541e6..000000000000
--- a/android/source/src/java/org/libreoffice/storage/external/OTGDocumentsProvider.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package org.libreoffice.storage.external;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
-import android.preference.PreferenceManager;
-import android.util.Log;
-
-import org.libreoffice.R;
-import org.libreoffice.storage.DocumentProviderSettingsActivity;
-import org.libreoffice.storage.IFile;
-import org.libreoffice.storage.IOUtils;
-import org.libreoffice.storage.local.LocalFile;
-
-import java.io.File;
-import java.net.URI;
-
-/**
- * TODO: OTG currently uses LocalFile. Change to an IFile that handles abrupt OTG unmounting
- */
-public class OTGDocumentsProvider implements IExternalDocumentProvider,
- SharedPreferences.OnSharedPreferenceChangeListener {
-
- private static final String LOGTAG = OTGDocumentsProvider.class.getSimpleName();
-
- private String rootPathURI;
- private int id;
-
- public OTGDocumentsProvider(int id, Context context) {
- this.id = id;
- setupRootPath(context);
- }
-
- private void setupRootPath(Context context) {
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
- rootPathURI = preferences.getString(
- DocumentProviderSettingsActivity.KEY_PREF_OTG_PATH_URI, "");
- }
-
- @Override
- public IFile createFromUri(Context context, URI uri) {
- return new LocalFile(uri);
- }
-
- @Override
- public int getNameResource() {
- return R.string.otg_file_system;
- }
-
- @Override
- public int getId() {
- return id;
- }
-
- @Override
- public IFile getRootDirectory(Context context) {
- // TODO: handle this with more fine-grained exceptions
- if(rootPathURI.equals("")) {
- Log.e(LOGTAG, "rootPathURI is empty");
- throw new RuntimeException(context.getString(R.string.ext_document_provider_error));
- }
-
- File f = IOUtils.getFileFromURIString(rootPathURI);
- if(IOUtils.isInvalidFile(f)) {
- Log.e(LOGTAG, "rootPathURI is invalid - missing device?");
- throw new RuntimeException(context.getString(R.string.otg_missing_error));
- }
-
- return new LocalFile(f);
- }
-
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (key.equals(DocumentProviderSettingsActivity.KEY_PREF_OTG_PATH_URI)) {
- rootPathURI = sharedPreferences.getString(key, "");
- }
- }
-
- @Override
- public String guessRootURI(Context context) {
- return "";
- }
-
- @Override
- public boolean checkProviderAvailability(Context context) {
- // check if system supports USB Host
- return rootPathURI.length()>0 && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_USB_HOST);
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/local/LocalDocumentsDirectoryProvider.java b/android/source/src/java/org/libreoffice/storage/local/LocalDocumentsDirectoryProvider.java
deleted file mode 100644
index 15522e93a45e..000000000000
--- a/android/source/src/java/org/libreoffice/storage/local/LocalDocumentsDirectoryProvider.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage.local;
-
-import java.io.File;
-
-import org.libreoffice.storage.IFile;
-import org.libreoffice.R;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Environment;
-import android.support.v4.content.ContextCompat;
-import android.util.Log;
-
-/**
- * A convenience IDocumentProvider to browse the /sdcard/Documents directory.
- *
- * Extends LocalDocumentsProvider to overwrite getRootDirectory and set it to
- * /sdcard/Documents. Most documents will probably be stored there so there is
- * no need for the user to browse the filesystem from the root every time.
- */
-public class LocalDocumentsDirectoryProvider extends LocalDocumentsProvider {
-
- public LocalDocumentsDirectoryProvider(int id) {
- super(id);
- }
-
- private static File getDocumentsDir() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
- // DIRECTORY_DOCUMENTS is 19 or later only
- return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS);
- } else {
- return new File(Environment.getExternalStorageDirectory() + "/Documents");
- }
- }
-
- @Override
- public IFile getRootDirectory(Context context) {
- File documentsDirectory = getDocumentsDir();
- if (!documentsDirectory.exists()) {
- if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
- if(!documentsDirectory.mkdirs()) {
- // fallback to the toplevel dir - might be due to the dir not mounted/used as USB-Mass-Storage or similar
- // TODO: handle unavailability of the storage/failure of the mkdir properly
- Log.e("LocalDocumentsProvider", "not sure how we ended up here - if we have read permissions to use it in the first place, we also should have the write-permissions..");
- documentsDirectory = Environment.getExternalStorageDirectory();
- }
- }
- }
- return new LocalFile(documentsDirectory);
- }
-
- @Override
- public int getNameResource() {
- return R.string.local_documents;
- }
-
- @Override
- public boolean checkProviderAvailability(Context context) {
- File documentsDirectory = getDocumentsDir();
- return documentsDirectory.exists() && ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java b/android/source/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java
deleted file mode 100644
index 1a10fad424db..000000000000
--- a/android/source/src/java/org/libreoffice/storage/local/LocalDocumentsProvider.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage.local;
-
-import java.net.URI;
-
-import org.libreoffice.storage.IDocumentProvider;
-import org.libreoffice.storage.IFile;
-
-import org.libreoffice.R;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Environment;
-import android.support.v4.content.ContextCompat;
-
-/**
- * Implementation of IDocumentProvider for the local file system.
- */
-public class LocalDocumentsProvider implements IDocumentProvider {
-
- private int id;
-
- public LocalDocumentsProvider(int id) {
- this.id = id;
- }
-
- @Override
- public IFile getRootDirectory(Context context) {
- return new LocalFile(Environment.getExternalStorageDirectory());
- }
-
- @Override
- public IFile createFromUri(Context context, URI uri) {
- return new LocalFile(uri);
- }
-
- @Override
- public int getNameResource() {
- return R.string.local_file_system;
- }
-
- @Override
- public int getId() {
- return id;
- }
-
- @Override
- public boolean checkProviderAvailability(Context context) {
- return ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/local/LocalFile.java b/android/source/src/java/org/libreoffice/storage/local/LocalFile.java
deleted file mode 100644
index 4ff5bbf119f4..000000000000
--- a/android/source/src/java/org/libreoffice/storage/local/LocalFile.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-package org.libreoffice.storage.local;
-
-import android.content.Context;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.libreoffice.storage.IFile;
-
-/**
- * Implementation of IFile for the local file system.
- */
-public class LocalFile implements IFile {
-
- private File file;
-
- public LocalFile(File file) {
- this.file = file;
- }
-
- public LocalFile(URI uri) {
- this.file = new File(uri);
- }
-
- public URI getUri() {
- return file.toURI();
- }
-
- public String getName() {
- return file.getName();
- }
-
- @Override
- public boolean isDirectory() {
- return file.isDirectory();
- }
-
- @Override
- public long getSize() {
- return file.length();
- }
-
- @Override
- public Date getLastModified() {
- return new Date(file.lastModified());
- }
-
- @Override
- public List<IFile> listFiles() {
- List<IFile> children = new ArrayList<IFile>();
- for (File child : file.listFiles()) {
- children.add(new LocalFile(child));
- }
- return children;
- }
-
- @Override
- public List<IFile> listFiles(FileFilter filter) {
- List<IFile> children = new ArrayList<IFile>();
- for (File child : file.listFiles(filter)) {
- children.add(new LocalFile(child));
- }
- return children;
- }
-
- @Override
- public IFile getParent(Context context) {
- return new LocalFile(file.getParentFile());
- }
-
- @Override
- public File getDocument() {
- return file;
- }
-
- @Override
- public boolean equals(Object object) {
- if (this == object)
- return true;
- if (!(object instanceof LocalFile))
- return false;
- LocalFile file = (LocalFile) object;
- return file.getUri().equals(getUri());
- }
-
- @Override
- public void saveDocument(File file) {
- // do nothing; file is local
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java b/android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
deleted file mode 100644
index fa74a54b08e2..000000000000
--- a/android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package org.libreoffice.storage.owncloud;
-
-import android.content.Context;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.libreoffice.storage.IFile;
-
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.resources.files.ChunkedUploadRemoteFileOperation;
-import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
-import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
-import com.owncloud.android.lib.resources.files.RemoteFile;
-import com.owncloud.android.lib.resources.files.UploadRemoteFileOperation;
-
-/**
- * Implementation of IFile for ownCloud servers.
- */
-public class OwnCloudFile implements IFile {
-
- private OwnCloudProvider provider;
- private RemoteFile file;
-
- private String name;
- private String parentPath;
-
- protected OwnCloudFile(OwnCloudProvider provider, RemoteFile file) {
- this.provider = provider;
- this.file = file;
-
- // get name and parent from path
- File localFile = new File(file.getRemotePath());
- this.name = localFile.getName();
- this.parentPath = localFile.getParent();
- }
-
- @Override
- public URI getUri(){
-
- try{
- return URI.create(URLEncoder.encode(file.getRemotePath(),"UTF-8"));
- }catch(UnsupportedEncodingException e){
- e.printStackTrace();
- }
-
- return null;
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public boolean isDirectory() {
- return file.getMimeType().equals("DIR");
- }
-
- @Override
- public long getSize() {
- return file.getLength();
- }
-
- @Override
- public Date getLastModified() {
- return new Date(file.getModifiedTimestamp());
- }
-
- @Override
- public List<IFile> listFiles() {
- List<IFile> children = new ArrayList<IFile>();
- if (isDirectory()) {
- ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(
- file.getRemotePath());
- RemoteOperationResult result = refreshOperation.execute(provider
- .getClient());
- if (!result.isSuccess()) {
- throw provider.buildRuntimeExceptionForResultCode(result.getCode());
- }
- for (Object obj : result.getData()) {
- RemoteFile child = (RemoteFile) obj;
- if (!child.getRemotePath().equals(file.getRemotePath()))
- children.add(new OwnCloudFile(provider, child));
- }
- }
- return children;
- }
-
- @Override
- public List<IFile> listFiles(FileFilter filter) {
- List<IFile> children = new ArrayList<IFile>();
- if (isDirectory()) {
- ReadRemoteFolderOperation refreshOperation = new ReadRemoteFolderOperation(
- file.getRemotePath());
- RemoteOperationResult result = refreshOperation.execute(provider
- .getClient());
- if (!result.isSuccess()) {
- throw provider.buildRuntimeExceptionForResultCode(result.getCode());
- }
-
- for (Object obj : result.getData()) {
- RemoteFile child = (RemoteFile) obj;
- if (!child.getRemotePath().equals(file.getRemotePath())){
- OwnCloudFile ownCloudFile = new OwnCloudFile(provider, child);
- if(!ownCloudFile.isDirectory()){
- File f = new File(provider.getCacheDir().getAbsolutePath(),
- ownCloudFile.getName());
- if(filter.accept(f))
- children.add(ownCloudFile);
- f.delete();
- }else{
- children.add(ownCloudFile);
- }
- }
- }
- }
- return children;
- }
-
- @Override
- public IFile getParent(Context context) {
- if (parentPath == null)
- // this is the root node
- return null;
-
- return provider.createFromUri(context, URI.create(parentPath));
- }
-
- @Override
- public File getDocument() {
- if (isDirectory()) {
- return null;
- }
- File downFolder = provider.getCacheDir();
- DownloadRemoteFileOperation operation = new DownloadRemoteFileOperation(
- file.getRemotePath(), downFolder.getAbsolutePath());
- RemoteOperationResult result = operation.execute(provider.getClient());
- if (!result.isSuccess()) {
- throw provider.buildRuntimeExceptionForResultCode(result.getCode());
- }
- return new File(downFolder.getAbsolutePath() + file.getRemotePath());
- }
-
- @Override
- public boolean equals(Object object) {
- if (this == object)
- return true;
- if (!(object instanceof OwnCloudFile))
- return false;
- OwnCloudFile file = (OwnCloudFile) object;
- return file.getUri().equals(getUri());
- }
-
- @Override
- public void saveDocument(File newFile) {
- UploadRemoteFileOperation uploadOperation;
- if (newFile.length() > ChunkedUploadRemoteFileOperation.CHUNK_SIZE) {
- uploadOperation = new ChunkedUploadRemoteFileOperation(
- newFile.getPath(), file.getRemotePath(), file.getMimeType());
- } else {
- uploadOperation = new UploadRemoteFileOperation(newFile.getPath(),
- file.getRemotePath(), file.getMimeType());
- }
-
- RemoteOperationResult result = uploadOperation.execute(provider
- .getClient());
- if (!result.isSuccess()) {
- throw provider.buildRuntimeExceptionForResultCode(result.getCode());
- }
- }
-}
diff --git a/android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java b/android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
deleted file mode 100644
index 0852ab617660..000000000000
--- a/android/source/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.libreoffice.storage.owncloud;
-
-import java.io.File;
-import java.net.URI;
-
-import org.libreoffice.R;
-import org.libreoffice.storage.DocumentProviderSettingsActivity;
-import org.libreoffice.storage.IDocumentProvider;
-import org.libreoffice.storage.IFile;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
-import android.net.Uri;
-import android.preference.PreferenceManager;
-
-import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.lib.common.OwnCloudClientFactory;
-import com.owncloud.android.lib.common.OwnCloudCredentialsFactory;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
-import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.lib.resources.files.FileUtils;
-import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
-import com.owncloud.android.lib.resources.files.RemoteFile;
-
-
-/**
- * Implementation of IDocumentProvider for ownCloud servers.
- */
-public class OwnCloudProvider implements IDocumentProvider,
- OnSharedPreferenceChangeListener {
-
- private int id;
-
- private Context context;
- private OwnCloudClient client;
- private File cacheDir;
-
- private String serverUrl;
- private String userName;
- private String password;
- private RemoteOperationResult result;
-
- public OwnCloudProvider(int id, Context context) {
- this.id = id;
- this.context = context;
-
- // read preferences
- SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
- serverUrl = preferences.getString(
- DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_SERVER, "");
- userName = preferences.getString(
- DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_USER_NAME, "");
- password = preferences.getString(
- DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_PASSWORD, "");
-
- setupClient();
-
- // make sure cache directory exists, and clear it
- // TODO: probably we should do smarter cache management
- cacheDir = new File(context.getCacheDir(), "ownCloud");
- if (cacheDir.exists()) {
- deleteRecursive(cacheDir);
- }
- cacheDir.mkdirs();
- }
-
- private void setupClient() {
- Uri serverUri = Uri.parse(serverUrl);
- client = OwnCloudClientFactory.createOwnCloudClient(serverUri, context,
- true);
- client.setCredentials(OwnCloudCredentialsFactory.newBasicCredentials(
- userName, password));
- }
-
- @Override
- public IFile getRootDirectory(Context context) {
- return createFromUri(context, URI.create(FileUtils.PATH_SEPARATOR));
- }
-
- @Override
- public IFile createFromUri(Context context, URI uri) {
- if(serverUrl != "" || userName != "" || password != ""){
- ReadRemoteFileOperation refreshOperation = new ReadRemoteFileOperation(
- uri.getPath());
- this.result = refreshOperation.execute(client);
- if (!result.isSuccess()) {
- throw buildRuntimeExceptionForResultCode(result.getCode());
- }
- if (result.getData().size() > 0) {
- return new OwnCloudFile(this, (RemoteFile) result.getData().get(0));
- }
- } else {
- throw buildRuntimeExceptionForResultCode(ResultCode.WRONG_CONNECTION);
- }
-
- return null;
- }
-
- @Override
- public int getNameResource() {
- return R.string.owncloud;
- }
-
- /**
- * Used by OwnCloudFiles to get a configured client to run their own
- * operations.
- *
- * @return configured OwnCloudClient.
- */
- protected OwnCloudClient getClient() {
- return client;
- }
-
- /**
- * Used by OwnCloudFiles to get the cache directory they should download
- * files to.
- *
- * @return cache directory.
- */
- protected File getCacheDir() {
- return cacheDir;
- }
-
- /**
- * Build the proper RuntimeException for some error result.
- *
- * @param code Result code got from some RemoteOperationResult.
- * @return exception with the proper internationalized error message.
- */
- protected RuntimeException buildRuntimeExceptionForResultCode(ResultCode code) {
- int errorMessage;
- switch (code) {
- case WRONG_CONNECTION: // SocketException
- case FILE_NOT_FOUND: // HTTP 404
- errorMessage = R.string.owncloud_wrong_connection;
- break;
- case UNAUTHORIZED: // wrong user/pass
- errorMessage = R.string.owncloud_unauthorized;
- break;
- default:
- errorMessage = R.string.owncloud_unspecified_error;
- break;
- }
- return new RuntimeException(context.getString(errorMessage));
- }
-
- /**
- * Deletes files and recursively deletes directories.
- *
- * @param file
- * File or directory to be deleted.
- */
- private static void deleteRecursive(File file) {
- if (file.isDirectory()) {
- for (File child : file.listFiles())
- deleteRecursive(child);
- }
- file.delete();
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences preferences,
- String key) {
- boolean changed = false;
- if (key.equals(DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_SERVER)) {
- serverUrl = preferences.getString(key, "");
- changed = true;
- }
- else if (key.equals(DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_USER_NAME)) {
- userName = preferences.getString(key, "");
- changed = true;
- }
- else if (key.equals(DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_PASSWORD)) {
- password = preferences.getString(key, "");
- changed = true;
- }
-
- if (changed)
- setupClient();
- }
-
- @Override
- public int getId() {
- return id;
- }
-
- @Override
- public boolean checkProviderAvailability(Context context) {
- return client != null;
- }
-}
diff --git a/android/source/src/java/org/libreoffice/ui/FileUtilities.java b/android/source/src/java/org/libreoffice/ui/FileUtilities.java
index 7a58486004cd..7fc8c3c84eb1 100644
--- a/android/source/src/java/org/libreoffice/ui/FileUtilities.java
+++ b/android/source/src/java/org/libreoffice/ui/FileUtilities.java
@@ -8,25 +8,18 @@
*/
package org.libreoffice.ui;
-import org.libreoffice.storage.IFile;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FilenameFilter;
-import java.text.Collator;
import java.util.Map;
-import java.util.Collections;
-import java.util.List;
import java.util.HashMap;
-import java.util.Comparator;
+
+import android.content.ContentResolver;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.OpenableColumns;
import android.util.Log;
-import android.webkit.MimeTypeMap;
public class FileUtilities {
- private static String LOGTAG = FileUtilities.class.getSimpleName();
-
- static final int ALL = -1;
+ private static final String LOGTAG = FileUtilities.class.getSimpleName();
// These have to be in sync with the file_view_modes resource.
static final int DOC = 0;
@@ -36,26 +29,16 @@ public class FileUtilities {
static final int UNKNOWN = 10;
- static final int SORT_AZ = 0;
- static final int SORT_ZA = 1;
- /** Oldest Files First*/
- static final int SORT_OLDEST = 2;
- /** Newest Files First*/
- static final int SORT_NEWEST = 3;
- /** Largest Files First */
- static final int SORT_LARGEST = 4;
- /** Smallest Files First */
- static final int SORT_SMALLEST = 5;
-
- public static final String DEFAULT_WRITER_EXTENSION = ".odt";
- public static final String DEFAULT_IMPRESS_EXTENSION = ".odp";
- public static final String DEFAULT_SPREADSHEET_EXTENSION = ".ods";
- public static final String DEFAULT_DRAWING_EXTENSION = ".odg";
+ public static final String MIMETYPE_OPENDOCUMENT_TEXT = "application/vnd.oasis.opendocument.text";
+ public static final String MIMETYPE_OPENDOCUMENT_SPREADSHEET = "application/vnd.oasis.opendocument.spreadsheet";
+ public static final String MIMETYPE_OPENDOCUMENT_PRESENTATION = "application/vnd.oasis.opendocument.presentation";
+ public static final String MIMETYPE_OPENDOCUMENT_GRAPHICS = "application/vnd.oasis.opendocument.graphics";
+ public static final String MIMETYPE_PDF = "application/pdf";
private static final Map<String, Integer> mExtnMap = new HashMap<String, Integer>();
- private static final Map<String, String> extensionToMimeTypeMap = new HashMap<String, String>();
static {
// Please keep this in sync with AndroidManifest.xml
+ // and 'SUPPORTED_MIME_TYPES' in LibreOfficeUIActivity.java
// ODF
mExtnMap.put(".odt", DOC);
@@ -80,7 +63,7 @@ public class FileUtilities {
mExtnMap.put(".vsdx", DRAWING);
mExtnMap.put(".pub", DRAWING);
mExtnMap.put(".ppt", IMPRESS);
- // mExtnMap.put(".pps", IMPRESS);
+ mExtnMap.put(".pps", IMPRESS);
mExtnMap.put(".xls", CALC);
// MS templates
@@ -91,7 +74,7 @@ public class FileUtilities {
// OOXML
mExtnMap.put(".docx", DOC);
mExtnMap.put(".pptx", IMPRESS);
- // mExtnMap.put(".ppsx", IMPRESS);
+ mExtnMap.put(".ppsx", IMPRESS);
mExtnMap.put(".xlsx", CALC);
// OOXML templates
@@ -109,22 +92,6 @@ public class FileUtilities {
mExtnMap.put(".svm", DRAWING);
mExtnMap.put(".wmf", DRAWING);
mExtnMap.put(".svg", DRAWING);
-
- // Some basic MIME types
- // Android's MimeTypeMap lacks some types that we need
- extensionToMimeTypeMap.put("odb", "application/vnd.oasis.opendocument.database");
- extensionToMimeTypeMap.put("odf", "application/vnd.oasis.opendocument.formula");
- extensionToMimeTypeMap.put("odg", "application/vnd.oasis.opendocument.graphics");
- extensionToMimeTypeMap.put("otg", "application/vnd.oasis.opendocument.graphics-template");
- extensionToMimeTypeMap.put("odi", "application/vnd.oasis.opendocument.image");
- extensionToMimeTypeMap.put("odp", "application/vnd.oasis.opendocument.presentation");
- extensionToMimeTypeMap.put("otp", "application/vnd.oasis.opendocument.presentation-template");
- extensionToMimeTypeMap.put("ods", "application/vnd.oasis.opendocument.spreadsheet");
- extensionToMimeTypeMap.put("ots", "application/vnd.oasis.opendocument.spreadsheet-template");
- extensionToMimeTypeMap.put("odt", "application/vnd.oasis.opendocument.text");
- extensionToMimeTypeMap.put("odm", "application/vnd.oasis.opendocument.text-master");
- extensionToMimeTypeMap.put("ott", "application/vnd.oasis.opendocument.text-template");
- extensionToMimeTypeMap.put("oth", "application/vnd.oasis.opendocument.text-web");
}
public static String getExtension(String filename) {
@@ -149,129 +116,42 @@ public class FileUtilities {
return type;
}
- static String getMimeType(String filename) {
- String extension = MimeTypeMap.getFileExtensionFromUrl(filename);
- String mime = extensionToMimeTypeMap.get(extension);
- if (mime == null) {
- //fallback to Android's MimeTypeMap
- mime = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
- extension);
- }
- return mime;
+ /**
+ * Returns whether the passed MIME type is one for a document template.
+ */
+ public static boolean isTemplateMimeType(final String mimeType) {
+ // this works for ODF and OOXML template MIME types
+ return mimeType != null && mimeType.endsWith("template");
}
- // Filter by mode, and/or in future by filename/wildcard
- private static boolean doAccept(String filename, int byMode, String byFilename) {
- Log.d(LOGTAG, "doAccept : " + filename + " mode " + byMode + " byFilename " + byFilename);
- if (filename == null)
- return false;
-
- // check extension
- if (byMode != ALL) {
- if (mExtnMap.get (getExtension (filename)) != byMode)
- return false;
- }
- if (!byFilename.equals("")) {
- // FIXME return false on a non-match
- }
- return true;
+ public static String stripExtensionFromFileName(final String fileName)
+ {
+ return fileName.split("\\.[A-Za-z0-9]*$")[0];
}
- static FileFilter getFileFilter(final int mode) {
- return new FileFilter() {
- public boolean accept(File pathname) {
- if (pathname.isDirectory())
- return true;
- if (lookupExtension(pathname.getName()) == UNKNOWN)
- return false;
- return doAccept(pathname.getName(), mode, "");
+ /**
+ * Tries to retrieve the display (which should be the document name)
+ * for the given URI using the given resolver.
+ */
+ public static String retrieveDisplayNameForDocumentUri(ContentResolver resolver, Uri docUri) {
+ String displayName = "";
+ // try to retrieve original file name
+ Cursor cursor = null;
+ try {
+ String[] columns = {OpenableColumns.DISPLAY_NAME};
+ cursor = resolver.query(docUri, columns, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ displayName = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
}
- };
- }
-
- static FilenameFilter getFilenameFilter(final int mode) {
- return new FilenameFilter() {
- public boolean accept(File dir, String filename) {
- if (new File(dir , filename).isDirectory())
- return true;
- return doAccept(filename, mode, "");
+ } catch (SecurityException e) {
+ // thrown e.g. when Uri has become invalid, e.g. corresponding file has been deleted
+ Log.i(LOGTAG, "SecurityException when trying to receive display name for Uri " + docUri);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
}
- };
- }
-
- static void sortFiles(List<IFile> files, int sortMode) {
- if (files == null)
- return;
- // Compare filenames in the default locale
- final Collator mCollator = Collator.getInstance();
- switch (sortMode) {
- case SORT_AZ:
- Collections.sort(files , new Comparator<IFile>() {
- public int compare(IFile lhs, IFile rhs) {
- return mCollator.compare(lhs.getName(), rhs.getName());
- }
- });
- break;
- case SORT_ZA:
- Collections.sort(files , new Comparator<IFile>() {
- public int compare(IFile lhs, IFile rhs) {
- return mCollator.compare(rhs.getName(), lhs.getName());
- }
- });
- break;
- case SORT_OLDEST:
- Collections.sort(files , new Comparator<IFile>() {
- public int compare(IFile lhs, IFile rhs) {
- return lhs.getLastModified().compareTo(rhs.getLastModified());
- }
- });
- break;
- case SORT_NEWEST:
- Collections.sort(files , new Comparator<IFile>() {
- public int compare(IFile lhs, IFile rhs) {
- return rhs.getLastModified().compareTo(lhs.getLastModified());
- }
- });
- break;
- case SORT_LARGEST:
- Collections.sort(files , new Comparator<IFile>() {
- public int compare(IFile lhs, IFile rhs) {
- return Long.valueOf(rhs.getSize()).compareTo(lhs.getSize());
- }
- });
- break;
- case SORT_SMALLEST:
- Collections.sort(files , new Comparator<IFile>() {
- public int compare(IFile lhs, IFile rhs) {
- return Long.valueOf(lhs.getSize()).compareTo(rhs.getSize());
- }
- });
- break;
- default:
- Log.e(LOGTAG, "uncatched sortMode: " + sortMode);
}
- }
-
- static boolean isHidden(File file) {
- return file.getName().startsWith(".");
- }
-
- static boolean isThumbnail(File file) {
- return isHidden(file) && file.getName().endsWith(".png");
- }
-
- static boolean hasThumbnail(File file) {
- String filename = file.getName();
- if (lookupExtension(filename) == DOC) // only do this for docs for now
- {
- // Will need another method to check if Thumb is up-to-date - or extend this one?
- return new File(file.getParent(), getThumbnailName(file)).isFile();
- }
- return true;
- }
-
- static String getThumbnailName(File file) {
- return "." + file.getName().split("[.]")[0] + ".png" ;
+ return displayName;
}
}
diff --git a/android/source/src/java/org/libreoffice/ui/FolderIconView.java b/android/source/src/java/org/libreoffice/ui/FolderIconView.java
deleted file mode 100644
index cde6cd27af4c..000000000000
--- a/android/source/src/java/org/libreoffice/ui/FolderIconView.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-package org.libreoffice.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.RectF;
-import android.graphics.Color;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
-
-import java.io.File;
-import java.util.Stack;
-
-public class FolderIconView extends View{
- private String LOGTAG = "FolderIconView";
-
- private Paint mPaintBlack;
- private Paint mPaintGray;
- private Paint mPaintShadow;
-
- private File dir;
-
- public FolderIconView(Context context) {
- super(context);
- initialisePaints();
- }
- public FolderIconView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initialisePaints();
- }
- public FolderIconView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- initialisePaints();
- }
-
- private void initialisePaints() {
- mPaintBlack = new Paint();
- mPaintBlack.setColor(Color.DKGRAY);//Can also use parseColor(String "#aarrggbb")
- mPaintBlack.setAntiAlias(true);
-
- mPaintGray = new Paint();
- mPaintGray.setColor(Color.GRAY);//Can also use parseColor(String "#aarrggbb")
- mPaintGray.setAntiAlias(true);
-
- mPaintShadow = new Paint();
- mPaintShadow.setColor(Color.parseColor("#88888888"));
- mPaintShadow.setAntiAlias(true);
- }
-
- public void setDir(File dir) {
- this.dir = dir;
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- Log.d(LOGTAG, "onDraw");
- //float width = (float)canvas.getWidth();
- //float height = (float)canvas.getHeight();
- float width = (float) this.getWidth();
- float height = (float) this.getHeight();
- float centerX = width*0.5f;// centered on horz axis
- float centerY = height*0.5f;
- float outerRadius = 0.8f*0.5f*width;
- float innerRadius = 0.7f*0.5f*width;
- float thumbHeight = outerRadius*1.25f;
- float thumbWidth = thumbHeight*(float)(1/Math.sqrt(2));
- float DZx = 0.2f*outerRadius;
- float DZy = 0.2f*outerRadius;
- //Bitmap blankPage = BitmapFactory.decodeResource(getResources(), R.drawable.page);
- Log.i(LOGTAG, Float.toString(width) + "x" + Float.toString(height));
- canvas.drawCircle(centerX, centerY, outerRadius, mPaintGray);
- canvas.drawCircle(centerX, centerY, innerRadius, mPaintBlack);
- //Either get thumbs from directory or use generic page images
- //For now just get the first 4 thumbs -> add some checks later
- if (dir == null)
- return;//TODO
- File[] contents = dir.listFiles();//TODO consider filtering thumbs to match grid.
- if (contents == null)
- // dir is not a directory,
- // or user does not have permissions to read it
- return;
- Stack<Bitmap> thumbs = new Stack<Bitmap>();
- BitmapFactory factory = new BitmapFactory();
- for (File file : contents) {
- if (!FileUtilities.isThumbnail(file))
- continue;
- thumbs.push(BitmapFactory.decodeFile(file.getAbsolutePath()));//TODO switch to push for semantics
- if (thumbs.size() > 3)
- break;
- }
- /*while(thumbs.size() < 4) {// padd out with blanks?
- thumbs.push(blankPage);
- }*/
- Log.i(LOGTAG, Integer.toString(thumbs.size()));
- //should handle empty folders better
- // options:
- // don't show?
- // show generic LO icons for writer etc
- // Show a generic blank page icon
- if (thumbs.isEmpty())
- return;
- /*float left = centerX ;//+ 0.25f*outerRadius;
- float top = centerY - 0.5f*outerRadius;
- float right = left + thumbs.get(0).getWidth()*0.4f;
- float bottom = top + thumbs.get(0).getHeight()*0.4f;
- RectF dest = new RectF(left, top, right, bottom);
- RectF shadowBox = new RectF(dest);
- shadowBox.inset(-1, -1);
- int size = thumbs.size();
- for (int i = 1; i <= size; i++) {
- canvas.drawRect(shadowBox, mPaintShadow);
- canvas.drawBitmap(thumbs.pop(), null, dest, null);
- dest.offset(-outerRadius*0.2f, outerRadius*0.1f);
- shadowBox.offset(-outerRadius*0.2f, outerRadius*0.1f);
- }*/
- float left;
- float top;
- float right;
- float bottom;
- RectF dest;
- RectF shadowBox;
- int size;
- switch(thumbs.size()) {
- case 0:
- break;
- case 1:
- left = centerX - 0.5f*thumbWidth;
- top = centerY - 0.5f*thumbHeight;
- right = left + thumbWidth;
- bottom = top + thumbHeight;
- dest = new RectF(left, top, right, bottom);
- shadowBox = new RectF(dest);
- shadowBox.inset(-1, -1);
- canvas.drawRect(shadowBox, mPaintShadow);
- canvas.drawBitmap(thumbs.pop(), null, dest, null);
- break;
- case 2:
- left = centerX - 0.5f*thumbWidth + 0.5f*DZx;
- top = centerY - 0.5f*thumbHeight - 0.5f*DZy;
- right = left + thumbWidth;
- bottom = top + thumbHeight;
- dest = new RectF(left, top, right, bottom);
- shadowBox = new RectF(dest);
- shadowBox.inset(-1, -1);
- size = thumbs.size();
- for (int i = 1; i <= size; i++) {
- canvas.drawRect(shadowBox, mPaintShadow);
- canvas.drawBitmap(thumbs.pop(), null, dest, null);
- dest.offset(-DZx, DZy);
- shadowBox.offset(-DZx, DZy);
- }
- break;
- case 3:
- left = centerX - 0.5f*thumbWidth + DZx;
- top = centerY - 0.5f*thumbHeight - DZy;
- right = left + thumbWidth;
- bottom = top + thumbHeight;
- dest = new RectF(left, top, right, bottom);
- shadowBox = new RectF(dest);
- shadowBox.inset(-1, -1);
- size = thumbs.size();
- for (int i = 1; i <= size; i++) {
- canvas.drawRect(shadowBox, mPaintShadow);
- canvas.drawBitmap(thumbs.pop(), null, dest, null);
- dest.offset(-DZx, DZy);
- shadowBox.offset(-DZx, DZy);
- }
- break;
- case 4:
- left = centerX - 0.5f*thumbWidth + 1.5f*DZx;
- top = centerY - 0.5f*thumbHeight - 1.5f*DZy;
- right = left + thumbWidth;
- bottom = top + thumbHeight;
- dest = new RectF(left, top, right, bottom);
- shadowBox = new RectF(dest);
- shadowBox.inset(-1, -1);
- size = thumbs.size();
- for (int i = 1; i <= size; i++) {
- canvas.drawRect(shadowBox, mPaintShadow);
- canvas.drawBitmap(thumbs.pop(), null, dest, null);
- dest.offset(-DZx, DZy);
- shadowBox.offset(-DZx, DZy);
- }
- break;
- default:
- break;
- }
- }
-
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index a9d797c4bf28..bc5203d9c6eb 100644
--- a/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/source/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -10,134 +10,119 @@
package org.libreoffice.ui;
import android.Manifest;
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
+import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
-import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
import android.graphics.drawable.Icon;
-import android.hardware.usb.UsbManager;
import android.net.Uri;
-import android.os.AsyncTask;
+import android.os.Build;
import android.os.Bundle;
-import android.os.Handler;
import android.preference.PreferenceManager;
-import android.support.annotation.NonNull;
-import android.support.design.widget.FloatingActionButton;
-import android.support.design.widget.NavigationView;
-import android.support.v4.app.ActivityCompat;
-import android.support.v4.content.ContextCompat;
-import android.support.v4.view.ViewCompat;
-import android.support.v4.widget.DrawerLayout;
-import android.support.v7.app.ActionBar;
-import android.support.v7.app.ActionBarDrawerToggle;
-import android.support.v7.app.AppCompatActivity;
-import android.support.v7.widget.GridLayoutManager;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.Toolbar;
-import android.text.InputType;
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.core.view.ViewCompat;
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.appcompat.widget.Toolbar;
+import android.text.TextUtils;
import android.util.Log;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.View.OnLongClickListener;
-import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.OvershootInterpolator;
-import android.widget.EditText;
-import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
-import android.widget.Toast;
import org.libreoffice.AboutDialogFragment;
-import org.libreoffice.LOKitShell;
+import org.libreoffice.BuildConfig;
import org.libreoffice.LibreOfficeMainActivity;
import org.libreoffice.LocaleHelper;
import org.libreoffice.R;
import org.libreoffice.SettingsActivity;
import org.libreoffice.SettingsListenerModel;
-import org.libreoffice.storage.DocumentProviderFactory;
-import org.libreoffice.storage.DocumentProviderSettingsActivity;
-import org.libreoffice.storage.IDocumentProvider;
-import org.libreoffice.storage.IFile;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FilenameFilter;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
public class LibreOfficeUIActivity extends AppCompatActivity implements SettingsListenerModel.OnSettingsPreferenceChangedListener, View.OnClickListener{
- private String LOGTAG = LibreOfficeUIActivity.class.getSimpleName();
- private SharedPreferences prefs;
- private int filterMode = FileUtilities.ALL;
- private int viewMode;
- private int sortMode;
- private boolean showHiddenFiles;
- private String displayLanguage;
-
- // dynamic permissions IDs
- private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
+ public enum DocumentType {
+ WRITER,
+ CALC,
+ IMPRESS,
+ DRAW,
+ INVALID
+ }
- FileFilter fileFilter;
- FilenameFilter filenameFilter;
- private List<IFile> filePaths = new ArrayList<IFile>();
- private DocumentProviderFactory documentProviderFactory;
- private IDocumentProvider documentProvider;
- private IFile homeDirectory;
- private IFile currentDirectory;
- private int currentlySelectedFile;
+ private static final String LOGTAG = LibreOfficeUIActivity.class.getSimpleName();
- private static final String CURRENT_DIRECTORY_KEY = "CURRENT_DIRECTORY";
- private static final String DOC_PROVIDER_KEY = "CURRENT_DOCUMENT_PROVIDER";
- private static final String FILTER_MODE_KEY = "FILTER_MODE";
- public static final String EXPLORER_VIEW_TYPE_KEY = "EXPLORER_VIEW_TYPE";
public static final String EXPLORER_PREFS_KEY = "EXPLORER_PREFS";
- public static final String SORT_MODE_KEY = "SORT_MODE";
- private static final String RECENT_DOCUMENTS_KEY = "RECENT_DOCUMENTS";
- private static final String ENABLE_SHOW_HIDDEN_FILES_KEY = "ENABLE_SHOW_HIDDEN_FILES";
+ private static final String RECENT_DOCUMENTS_KEY = "RECENT_DOCUMENT_URIS";
+ // delimiter used for storing multiple URIs in a string
+ private static final String RECENT_DOCUMENTS_DELIMITER = " ";
private static final String DISPLAY_LANGUAGE = "DISPLAY_LANGUAGE";
- public static final String NEW_FILE_PATH_KEY = "NEW_FILE_PATH_KEY";
public static final String NEW_DOC_TYPE_KEY = "NEW_DOC_TYPE_KEY";
public static final String NEW_WRITER_STRING_KEY = "private:factory/swriter";
public static final String NEW_IMPRESS_STRING_KEY = "private:factory/simpress";
public static final String NEW_CALC_STRING_KEY = "private:factory/scalc";
public static final String NEW_DRAW_STRING_KEY = "private:factory/sdraw";
- public static final int GRID_VIEW = 0;
- public static final int LIST_VIEW = 1;
+ // keep this in sync with 'AndroidManifext.xml'
+ private static final String[] SUPPORTED_MIME_TYPES = {
+ "application/vnd.oasis.opendocument.text",
+ "application/vnd.oasis.opendocument.graphics",
+ "application/vnd.oasis.opendocument.presentation",
+ "application/vnd.oasis.opendocument.spreadsheet",
+ "application/vnd.oasis.opendocument.text-flat-xml",
+ "application/vnd.oasis.opendocument.graphics-flat-xml",
+ "application/vnd.oasis.opendocument.presentation-flat-xml",
+ "application/vnd.oasis.opendocument.spreadsheet-flat-xml",
+ "application/vnd.oasis.opendocument.text-template",
+ "application/vnd.oasis.opendocument.spreadsheet-template",
+ "application/vnd.oasis.opendocument.graphics-template",
+ "application/vnd.oasis.opendocument.presentation-template",
+ "application/rtf",
+ "text/rtf",
+ "application/msword",
+ "application/vnd.ms-powerpoint",
+ "application/vnd.ms-excel",
+ "application/vnd.visio",
+ "application/vnd.visio.xml",
+ "application/x-mspublisher",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
+ "text/csv",
+ "text/comma-separated-values",
+ "application/vnd.ms-works",
+ "application/vnd.apple.keynote",
+ "application/x-abiword",
+ "application/x-pagemaker",
+ "image/x-emf",
+ "image/x-svm",
+ "image/x-wmf",
+ "image/svg+xml",
+ };
- private DrawerLayout drawerLayout;
- private NavigationView navigationDrawer;
- private ActionBar actionBar;
- private ActionBarDrawerToggle drawerToggle;
- private RecyclerView fileRecyclerView;
- private RecyclerView recentRecyclerView;
+ private static final int REQUEST_CODE_OPEN_FILECHOOSER = 12345;
- private boolean canQuit = false;
+ private static final int PERMISSION_WRITE_EXTERNAL_STORAGE = 0;
private Animation fabOpenAnimation;
private Animation fabCloseAnimation;
@@ -156,45 +141,49 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // initialize document provider factory
- DocumentProviderFactory.initialize(this);
- documentProviderFactory = DocumentProviderFactory.getInstance();
-
- PreferenceManager.setDefaultValues(this, R.xml.documentprovider_preferences, false);
readPreferences();
SettingsListenerModel.getInstance().setListener(this);
- // Registering the USB detect broadcast receiver
- IntentFilter filter = new IntentFilter();
- filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
- filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
- registerReceiver(mUSBReceiver, filter);
- // init UI and populate with contents from the provider
-
+ // init UI
createUI();
fabOpenAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_open);
fabCloseAnimation = AnimationUtils.loadAnimation(this, R.anim.fab_close);
}
@Override
+ protected void onStart() {
+ super.onStart();
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
+ Log.i(LOGTAG, "no permission to read external storage - asking for permission");
+ ActivityCompat.requestPermissions(this,
+ new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ PERMISSION_WRITE_EXTERNAL_STORAGE);
+ }
+ }
+
+ @Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(LocaleHelper.onAttach(newBase));
}
public void createUI() {
-
setContentView(R.layout.activity_document_browser);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
- actionBar = getSupportActionBar();
+ ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
- actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setIcon(R.mipmap.ic_launcher);
}
editFAB = findViewById(R.id.editFAB);
editFAB.setOnClickListener(this);
+ // allow creating new docs only when experimental editing is enabled
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ final boolean bEditingEnabled = BuildConfig.ALLOW_EDITING && preferences.getBoolean(LibreOfficeMainActivity.ENABLE_EXPERIMENTAL_PREFS_KEY, false);
+ editFAB.setVisibility(bEditingEnabled ? View.VISIBLE : View.INVISIBLE);
+
impressFAB = findViewById(R.id.newImpressFAB);
impressFAB.setOnClickListener(this);
writerFAB = findViewById(R.id.newWriterFAB);
@@ -207,110 +196,27 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
impressLayout = findViewById(R.id.impressLayout);
calcLayout = findViewById(R.id.calcLayout);
drawLayout = findViewById(R.id.drawLayout);
+ TextView openFileView = findViewById(R.id.open_file_button);
+ openFileView.setOnClickListener(this);
- recentRecyclerView = findViewById(R.id.list_recent);
- Set<String> recentFileStrings = prefs.getStringSet(RECENT_DOCUMENTS_KEY, new HashSet<String>());
+ RecyclerView recentRecyclerView = findViewById(R.id.list_recent);
- final ArrayList<IFile> recentFiles = new ArrayList<IFile>();
+ SharedPreferences prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE);
+ String recentPref = prefs.getString(RECENT_DOCUMENTS_KEY, "");
+ String[] recentFileStrings = recentPref.split(RECENT_DOCUMENTS_DELIMITER);
+
+ final List<RecentFile> recentFiles = new ArrayList<>();
for (String recentFileString : recentFileStrings) {
- try {
- if(documentProvider != null)
- recentFiles.add(documentProvider.createFromUri(this, new URI(recentFileString)));
- } catch (URISyntaxException e) {
- e.printStackTrace();
- } catch (RuntimeException e){
- e.printStackTrace();
+ Uri uri = Uri.parse(recentFileString);
+ String filename = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), uri);
+ if (!filename.isEmpty()) {
+ recentFiles.add(new RecentFile(uri, filename));
}
}
recentRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
recentRecyclerView.setAdapter(new RecentFilesAdapter(this, recentFiles));
-
- fileRecyclerView = findViewById(R.id.file_recycler_view);
- //This should be tested because it possibly disables view recycling
- fileRecyclerView.setNestedScrollingEnabled(false);
- openDirectory(currentDirectory);
- registerForContextMenu(fileRecyclerView);
-
- //Setting up navigation drawer
- drawerLayout = findViewById(R.id.drawer_layout);
- navigationDrawer = findViewById(R.id.navigation_drawer);
-
- final ArrayList<CharSequence> providerNames = new ArrayList<CharSequence>(
- Arrays.asList(documentProviderFactory.getNames())
- );
-
- // Loop through the document providers menu items and check if they are available or not
- for (int index = 0; index < providerNames.size(); index++) {
- MenuItem item = navigationDrawer.getMenu().getItem(index);
- item.setEnabled(documentProviderFactory.getProvider(index).checkProviderAvailability(this));
- }
-
- navigationDrawer.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
- @Override
- public boolean onNavigationItemSelected(@NonNull MenuItem item) {
-
- switch (item.getItemId()) {
- case R.id.menu_storage_preferences: {
- startActivity(new Intent(LibreOfficeUIActivity.this, DocumentProviderSettingsActivity.class));
- return true;
- }
-
- case R.id.menu_provider_documents: {
- switchToDocumentProvider(documentProviderFactory.getProvider(0));
- return true;
- }
-
- case R.id.menu_provider_filesystem: {
- switchToDocumentProvider(documentProviderFactory.getProvider(1));
- return true;
- }
-
- case R.id.menu_provider_extsd: {
- switchToDocumentProvider(documentProviderFactory.getProvider(2));
- return true;
- }
-
- case R.id.menu_provider_otg: {
- switchToDocumentProvider(documentProviderFactory.getProvider(3));
- return true;
- }
-
- case R.id.menu_provider_owncloud: {
- switchToDocumentProvider(documentProviderFactory.getProvider(4));
- return true;
- }
-
- default:
- return false;
- }
-
-
- }
- });
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
- R.string.document_locations, R.string.close_document_locations) {
-
- @Override
- public void onDrawerOpened(View drawerView) {
- super.onDrawerOpened(drawerView);
- supportInvalidateOptionsMenu();
- navigationDrawer.requestFocus(); // Make keypad navigation easier
- if (isFabMenuOpen) {
- collapseFabMenu(); //Collapse FAB Menu when drawer is opened
- }
- }
-
- @Override
- public void onDrawerClosed(View drawerView) {
- super.onDrawerClosed(drawerView);
- supportInvalidateOptionsMenu();
- }
- };
- drawerToggle.setDrawerIndicatorEnabled(true);
- drawerLayout.addDrawerListener(drawerToggle);
- drawerToggle.syncState();
}
private void expandFabMenu() {
@@ -340,658 +246,126 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
}
@Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
-
- drawerToggle.syncState();
- }
-
- private void refreshView() {
- // enable home icon as "up" if required
- if (currentDirectory != null && homeDirectory != null && !currentDirectory.equals(homeDirectory)) {
- drawerToggle.setDrawerIndicatorEnabled(false);
- } else {
- drawerToggle.setDrawerIndicatorEnabled(true);
- }
-
- FileUtilities.sortFiles(filePaths, sortMode);
- // refresh view
- fileRecyclerView.setLayoutManager(isViewModeList() ? new LinearLayoutManager(this) : new GridLayoutManager(this, 3));
- fileRecyclerView.setAdapter(new ExplorerItemAdapter(this, filePaths));
- // close drawer if it was open
- drawerLayout.closeDrawer(navigationDrawer);
+ public void onBackPressed() {
if (isFabMenuOpen) {
collapseFabMenu();
+ } else {
+ super.onBackPressed();
}
}
@Override
- public void onBackPressed() {
- if (drawerLayout.isDrawerOpen(navigationDrawer)) {
- drawerLayout.closeDrawer(navigationDrawer);
- if (isFabMenuOpen) {
- collapseFabMenu();
- }
- } else if (currentDirectory != null && homeDirectory != null && !currentDirectory.equals(homeDirectory)) {
- // navigate upwards in directory hierarchy
- openParentDirectory();
- } else if (isFabMenuOpen) {
- collapseFabMenu();
- } else {
- // only exit if warning has been shown
- if (canQuit) {
- super.onBackPressed();
- return;
- }
-
- // show warning about leaving the app and set a timer
- Toast.makeText(this, R.string.back_again_to_quit,
- Toast.LENGTH_SHORT).show();
- canQuit = true;
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- canQuit = false;
- }
- }, 3000);
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == REQUEST_CODE_OPEN_FILECHOOSER && resultCode == RESULT_OK) {
+ final Uri fileUri = data.getData();
+ openDocument(fileUri);
}
}
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v,
- ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.context_menu, menu);
- }
+ private void showSystemFilePickerAndOpenFile() {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.setType("*/*");
+ intent.putExtra(Intent.EXTRA_MIME_TYPES, SUPPORTED_MIME_TYPES);
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case R.id.context_menu_open:
- open(currentlySelectedFile);
- return true;
- case R.id.context_menu_share:
- share(currentlySelectedFile);
- return true;
- default:
- return super.onContextItemSelected(item);
+ try {
+ startActivityForResult(intent, REQUEST_CODE_OPEN_FILECHOOSER);
+ } catch (ActivityNotFoundException e) {
+ Log.w(LOGTAG, "No activity available that can handle the intent to open a document.");
}
}
- private boolean isViewModeList(){
- return viewMode == LIST_VIEW;
- }
-
- private void switchToDocumentProvider(IDocumentProvider provider) {
+ public void openDocument(final Uri documentUri) {
+ // "forward" to LibreOfficeMainActivity to open the file
+ Intent intent = new Intent(Intent.ACTION_VIEW, documentUri);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- new AsyncTask<IDocumentProvider, Void, Void>() {
- @Override
- protected Void doInBackground(IDocumentProvider... provider) {
- // switch document provider:
- // these operations may imply network access and must be run in
- // a different thread
- try {
- homeDirectory = provider[0].getRootDirectory(LibreOfficeUIActivity.this);
- List<IFile> paths = homeDirectory.listFiles(FileUtilities
- .getFileFilter(filterMode));
- filePaths = new ArrayList<IFile>();
- for(IFile file: paths) {
- if(showHiddenFiles){
- filePaths.add(file);
- } else {
- if(!file.getName().startsWith(".")){
- filePaths.add(file);
- }
- }
- }
- }
- catch (final RuntimeException e) {
- final Activity activity = LibreOfficeUIActivity.this;
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(activity, e.getMessage(),
- Toast.LENGTH_SHORT).show();
- }
- });
- startActivity(new Intent(activity, DocumentProviderSettingsActivity.class));
- Log.e(LOGTAG, "failed to switch document provider "+ e.getMessage(), e.getCause());
- return null;
- }
- //no exception
- documentProvider = provider[0];
- currentDirectory = homeDirectory;
- return null;
- }
+ addDocumentToRecents(documentUri);
- @Override
- protected void onPostExecute(Void result) {
- refreshView();
- }
- }.execute(provider);
+ String packageName = getApplicationContext().getPackageName();
+ ComponentName componentName = new ComponentName(packageName,
+ LibreOfficeMainActivity.class.getName());
+ intent.setComponent(componentName);
+ startActivity(intent);
}
- public void openDirectory(IFile dir) {
- if (dir == null)
- return;
-
- //show recent files if in home directory
- if (dir.equals(homeDirectory)) {
- recentRecyclerView.setVisibility(View.VISIBLE);
- findViewById(R.id.header_browser).setVisibility((View.VISIBLE));
- findViewById(R.id.header_recents).setVisibility((View.VISIBLE));
- actionBar.setTitle(R.string.app_name);
- findViewById(R.id.text_directory_path).setVisibility(View.GONE);
+ private void loadNewDocument(DocumentType docType) {
+ final String newDocumentType;
+ if (docType == DocumentType.WRITER) {
+ newDocumentType = NEW_WRITER_STRING_KEY;
+ } else if (docType == DocumentType.CALC) {
+ newDocumentType = NEW_CALC_STRING_KEY;
+ } else if (docType == DocumentType.IMPRESS) {
+ newDocumentType = NEW_IMPRESS_STRING_KEY;
+ } else if (docType == DocumentType.DRAW) {
+ newDocumentType = NEW_DRAW_STRING_KEY;
} else {
- recentRecyclerView.setVisibility(View.GONE);
- findViewById(R.id.header_browser).setVisibility((View.GONE));
- findViewById(R.id.header_recents).setVisibility((View.GONE));
- actionBar.setTitle(dir.getName());
- findViewById(R.id.text_directory_path).setVisibility(View.VISIBLE);
- ((TextView)findViewById(R.id.text_directory_path)).setText(getString(R.string.current_dir,
- dir.getUri().getPath()));
+ Log.w(LOGTAG, "invalid document type passed to loadNewDocument method. Ignoring request");
+ return;
}
- new AsyncTask<IFile, Void, Void>() {
- @Override
- protected Void doInBackground(IFile... dir) {
- // get list of files:
- // this operation may imply network access and must be run in
- // a different thread
- currentDirectory = dir[0];
- try {
- List<IFile> paths = currentDirectory.listFiles(FileUtilities
- .getFileFilter(filterMode));
- filePaths = new ArrayList<IFile>();
- for(IFile file: paths) {
- if(showHiddenFiles){
- filePaths.add(file);
- } else {
- if(!file.getName().startsWith(".")){
- filePaths.add(file);
- }
- }
- }
- }
- catch (final RuntimeException e) {
- final Activity activity = LibreOfficeUIActivity.this;
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(activity, e.getMessage(),
- Toast.LENGTH_SHORT).show();
- }
- });
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- refreshView();
- }
- }.execute(dir);
- }
-
- public void open(final IFile document) {
- addDocumentToRecents(document);
- new AsyncTask<IFile, Void, File>() {
- @Override
- protected File doInBackground(IFile... document) {
- // this operation may imply network access and must be run in
- // a different thread
- try {
- return document[0].getDocument();
- }
- catch (final RuntimeException e) {
- final Activity activity = LibreOfficeUIActivity.this;
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(activity, e.getMessage(),
- Toast.LENGTH_SHORT).show();
- }
- });
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(File file) {
- if (file != null) {
- Intent i = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));
- String packageName = getApplicationContext().getPackageName();
- ComponentName componentName = new ComponentName(packageName,
- LibreOfficeMainActivity.class.getName());
- i.setComponent(componentName);
-
- // these extras allow to rebuild the IFile object in LOMainActivity
- i.putExtra("org.libreoffice.document_provider_id",
- documentProvider.getId());
- i.putExtra("org.libreoffice.document_uri",
- document.getUri());
-
- startActivity(i);
- }
- }
- }.execute(document);
- }
-
- // Opens an Input dialog to get the name of new file
- private void createNewFileInputDialog(final String defaultFileName, final String newDocumentType) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle(R.string.create_new_document_title);
- final EditText input = new EditText(this);
- input.setInputType(InputType.TYPE_CLASS_TEXT);
- input.setText(defaultFileName);
- builder.setView(input);
-
- builder.setPositiveButton(R.string.action_create, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final String newFilePath = currentDirectory.getUri().getPath() + input.getText().toString();
- loadNewDocument(newDocumentType, newFilePath);
- }
- });
-
- builder.setNegativeButton(R.string.action_cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- dialog.cancel();
- }
- });
-
- builder.show();
- }
-
- private void loadNewDocument(String newDocumentType, String newFilePath) {
Intent intent = new Intent(LibreOfficeUIActivity.this, LibreOfficeMainActivity.class);
intent.putExtra(NEW_DOC_TYPE_KEY, newDocumentType);
- intent.putExtra(NEW_FILE_PATH_KEY, newFilePath);
startActivity(intent);
}
- private void open(int position) {
- IFile file = filePaths.get(position);
- if (!file.isDirectory()) {
- open(file);
- } else {
- openDirectory(file);
- }
- }
-
- private void openParentDirectory() {
- new AsyncTask<Void, Void, IFile>() {
- @Override
- protected IFile doInBackground(Void... dir) {
- // this operation may imply network access and must be run in
- // a different thread
- return currentDirectory.getParent(LibreOfficeUIActivity.this);
- }
-
- @Override
- protected void onPostExecute(IFile result) {
- openDirectory(result);
- }
- }.execute();
- }
-
- private void share(int position) {
-
- new AsyncTask<IFile, Void, File>() {
- @Override
- protected File doInBackground(IFile... document) {
- // this operation may imply network access and must be run in
- // a different thread
- try {
- return document[0].getDocument();
- } catch (final RuntimeException e) {
- final Activity activity = LibreOfficeUIActivity.this;
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- Toast.makeText(activity, e.getMessage(),
- Toast.LENGTH_SHORT).show();
- }
- });
- Log.e(LOGTAG, e.getMessage(), e.getCause());
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(File file) {
- if (file != null) {
- Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
- Uri uri = Uri.fromFile(file);
- sharingIntent.setType(FileUtilities.getMimeType(file.getName()));
- sharingIntent.putExtra(android.content.Intent.EXTRA_STREAM, uri);
- sharingIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
- file.getName());
- startActivity(Intent.createChooser(sharingIntent,
- getString(R.string.share_via)));
- }
- }
- }.execute(filePaths.get(position));
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.view_menu, menu);
- switch (sortMode) {
- case FileUtilities.SORT_SMALLEST: {
- menu.findItem(R.id.menu_sort_size_asc).setChecked(true);
- }
- break;
-
- case FileUtilities.SORT_LARGEST: {
- menu.findItem(R.id.menu_sort_size_desc).setChecked(true);
- }
- break;
-
- case FileUtilities.SORT_AZ: {
- menu.findItem(R.id.menu_sort_az).setChecked(true);
- }
- break;
-
- case FileUtilities.SORT_ZA: {
- menu.findItem(R.id.menu_sort_za).setChecked(true);
- }
- break;
-
- case FileUtilities.SORT_NEWEST: {
- menu.findItem(R.id.menu_sort_modified_newest).setChecked(true);
- }
- break;
-
- case FileUtilities.SORT_OLDEST: {
- menu.findItem(R.id.menu_sort_modified_oldest).setChecked(true);
- }
- break;
- }
-
- switch (filterMode) {
- case FileUtilities.ALL:
- menu.findItem(R.id.menu_filter_everything).setChecked(true);
- break;
-
- case FileUtilities.DOC:
- menu.findItem(R.id.menu_filter_documents).setChecked(true);
- break;
-
- case FileUtilities.CALC:
- menu.findItem(R.id.menu_filter_presentations).setChecked(true);
- break;
-
- case FileUtilities.IMPRESS:
- menu.findItem(R.id.menu_filter_presentations).setChecked(true);
- break;
-
- case FileUtilities.DRAWING:
- menu.findItem(R.id.menu_filter_drawings).setChecked(true);
- break;
- }
-
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
- // Will close the drawer if the home button is pressed
- if (drawerToggle.onOptionsItemSelected(item)) {
+ final int itemId = item.getItemId();
+ if (itemId == R.id.action_about) {
+ AboutDialogFragment aboutDialogFragment = new AboutDialogFragment();
+ aboutDialogFragment.show(getSupportFragmentManager(), "AboutDialogFragment");
return true;
}
-
- switch (item.getItemId()) {
- case android.R.id.home:
- if (!currentDirectory.equals(homeDirectory)){
- openParentDirectory();
- }
- break;
-
- case R.id.menu_filter_everything:
- item.setChecked(true);
- filterMode = FileUtilities.ALL;
- openDirectory(currentDirectory);
- break;
-
- case R.id.menu_filter_documents:
- item.setChecked(true);
- filterMode = FileUtilities.DOC;
- openDirectory(currentDirectory);
- break;
-
- case R.id.menu_filter_spreadsheets:
- item.setChecked(true);
- filterMode = FileUtilities.CALC;
- openDirectory(currentDirectory);
- break;
-
- case R.id.menu_filter_presentations:
- item.setChecked(true);
- filterMode = FileUtilities.IMPRESS;
- openDirectory(currentDirectory);
- break;
-
- case R.id.menu_filter_drawings:
- item.setChecked(true);
- filterMode = FileUtilities.DRAWING;
- openDirectory(currentDirectory);
- break;
-
- case R.id.menu_sort_size_asc: {
- sortMode = FileUtilities.SORT_SMALLEST;
- this.onResume();
- }
- break;
-
- case R.id.menu_sort_size_desc: {
- sortMode = FileUtilities.SORT_LARGEST;
- this.onResume();
- }
- break;
-
- case R.id.menu_sort_az: {
- sortMode = FileUtilities.SORT_AZ;
- this.onResume();
- }
- break;
-
- case R.id.menu_sort_za: {
- sortMode = FileUtilities.SORT_ZA;
- this.onResume();
- }
- break;
-
- case R.id.menu_sort_modified_newest: {
- sortMode = FileUtilities.SORT_NEWEST;
- this.onResume();
- }
- break;
-
- case R.id.menu_sort_modified_oldest: {
- sortMode = FileUtilities.SORT_OLDEST;
- this.onResume();
- }
- break;
-
- case R.id.action_about: {
- AboutDialogFragment aboutDialogFragment = new AboutDialogFragment();
- aboutDialogFragment.show(getSupportFragmentManager(), "AboutDialogFragment");
- }
- return true;
- case R.id.action_settings:
- startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
+ if (itemId == R.id.action_settings) {
+ startActivity(new Intent(getApplicationContext(), SettingsActivity.class));
+ return true;
}
- return true;
+
+ return super.onOptionsItemSelected(item);
}
public void readPreferences(){
- prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE);
- sortMode = prefs.getInt(SORT_MODE_KEY, FileUtilities.SORT_AZ);
SharedPreferences defaultPrefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
- viewMode = Integer.valueOf(defaultPrefs.getString(EXPLORER_VIEW_TYPE_KEY, ""+ GRID_VIEW));
- filterMode = Integer.valueOf(defaultPrefs.getString(FILTER_MODE_KEY , "-1"));
- showHiddenFiles = defaultPrefs.getBoolean(ENABLE_SHOW_HIDDEN_FILES_KEY, false);
- displayLanguage = defaultPrefs.getString(DISPLAY_LANGUAGE, LocaleHelper.SYSTEM_DEFAULT_LANGUAGE);
-
- Intent i = this.getIntent();
- if (i.hasExtra(CURRENT_DIRECTORY_KEY)) {
- try {
- currentDirectory = documentProvider.createFromUri(this, new URI(
- i.getStringExtra(CURRENT_DIRECTORY_KEY)));
- } catch (URISyntaxException e) {
- currentDirectory = documentProvider.getRootDirectory(this);
- }
- Log.d(LOGTAG, CURRENT_DIRECTORY_KEY);
- }
-
- if (i.hasExtra(FILTER_MODE_KEY)) {
- filterMode = i.getIntExtra( FILTER_MODE_KEY, FileUtilities.ALL);
- Log.d(LOGTAG, FILTER_MODE_KEY);
- }
-
- if (i.hasExtra(EXPLORER_VIEW_TYPE_KEY)) {
- viewMode = i.getIntExtra( EXPLORER_VIEW_TYPE_KEY, GRID_VIEW);
- Log.d(LOGTAG, EXPLORER_VIEW_TYPE_KEY);
- }
-
+ final String displayLanguage = defaultPrefs.getString(DISPLAY_LANGUAGE, LocaleHelper.SYSTEM_DEFAULT_LANGUAGE);
LocaleHelper.setLocale(this, displayLanguage);
}
@Override
public void settingsPreferenceChanged(SharedPreferences sharedPreferences, String key) {
readPreferences();
- refreshView();
- }
-
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- // TODO Auto-generated method stub
- super.onSaveInstanceState(outState);
-
- if(currentDirectory != null) {
- outState.putString(CURRENT_DIRECTORY_KEY, currentDirectory.getUri().toString());
- Log.d(LOGTAG, currentDirectory.toString() + Integer.toString(filterMode) + Integer.toString(viewMode));
- }
- outState.putInt(FILTER_MODE_KEY, filterMode);
- outState.putInt(EXPLORER_VIEW_TYPE_KEY , viewMode);
- if(documentProvider != null)
- outState.putInt(DOC_PROVIDER_KEY, documentProvider.getId());
-
- outState.putBoolean(ENABLE_SHOW_HIDDEN_FILES_KEY , showHiddenFiles);
-
- //prefs.edit().putInt(EXPLORER_VIEW_TYPE, viewType).commit();
- Log.d(LOGTAG, "savedInstanceState");
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- // TODO Auto-generated method stub
- super.onRestoreInstanceState(savedInstanceState);
- if (savedInstanceState.isEmpty()){
- return;
- }
- if (documentProvider == null) {
- Log.d(LOGTAG, "onRestoreInstanceState - documentProvider is null");
- documentProvider = DocumentProviderFactory.getInstance()
- .getProvider(savedInstanceState.getInt(DOC_PROVIDER_KEY));
- }
- try {
- currentDirectory = documentProvider.createFromUri(this, new URI(
- savedInstanceState.getString(CURRENT_DIRECTORY_KEY)));
- } catch (URISyntaxException e) {
- currentDirectory = documentProvider.getRootDirectory(this);
- }
- filterMode = savedInstanceState.getInt(FILTER_MODE_KEY, FileUtilities.ALL);
- viewMode = savedInstanceState.getInt(EXPLORER_VIEW_TYPE_KEY, GRID_VIEW);
- showHiddenFiles = savedInstanceState.getBoolean(ENABLE_SHOW_HIDDEN_FILES_KEY, false);
- //openDirectory(currentDirectory);
- Log.d(LOGTAG, "onRestoreInstanceState");
- Log.d(LOGTAG, currentDirectory.toString() + Integer.toString(filterMode) + Integer.toString(viewMode));
- }
-
- private final BroadcastReceiver mUSBReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
- Toast.makeText(context, R.string.usb_connected_configure, Toast.LENGTH_SHORT).show();
- startActivity(new Intent(context, DocumentProviderSettingsActivity.class));
- Log.d(LOGTAG, "USB device attached");
- } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {
- Log.d(LOGTAG, "USB device detached");
- }
- }
- };
- @Override
- protected void onPause() {
- super.onPause();
- Log.d(LOGTAG, "onPause");
}
@Override
protected void onResume() {
super.onResume();
Log.d(LOGTAG, "onResume");
- Log.d(LOGTAG, "sortMode="+ sortMode + " filterMode=" + filterMode);
createUI();
}
- @Override
- protected void onStart() {
- super.onStart();
- if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
- Log.i(LOGTAG, "no permission to read external storage - asking for permission");
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- PERMISSION_WRITE_EXTERNAL_STORAGE);
- } else {
- switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
- setEditFABVisibility(View.VISIBLE);
- }
- Log.d(LOGTAG, "onStart");
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- Log.d(LOGTAG, "onStop");
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- unregisterReceiver(mUSBReceiver);
- Log.d(LOGTAG, "onDestroy");
- }
-
- private int dpToPx(int dp){
- final float scale = getApplicationContext().getResources().getDisplayMetrics().density;
- return (int) (dp * scale + 0.5f);
- }
+ private void addDocumentToRecents(Uri fileUri) {
+ SharedPreferences prefs = getSharedPreferences(EXPLORER_PREFS_KEY, MODE_PRIVATE);
- private void addDocumentToRecents(IFile iFile) {
- String newRecent = iFile.getUri().toString();
- Set<String> recentsSet = prefs.getStringSet(RECENT_DOCUMENTS_KEY, new HashSet<String>());
+ // preserve permissions across device reboots,
+ // s. https://developer.android.com/training/data-storage/shared/documents-files#persist-permissions
+ getContentResolver().takePersistableUriPermission(fileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
- //create array to work with
- ArrayList<String> recentsArrayList = new ArrayList<String>(recentsSet);
+ String newRecent = fileUri.toString();
+ List<String> recentsList = new ArrayList<>(Arrays.asList(prefs.getString(RECENT_DOCUMENTS_KEY, "").split(RECENT_DOCUMENTS_DELIMITER)));
- //remove string if present, so that it doesn't appear multiple times
- recentsSet.remove(newRecent);
-
- //put the new value in the first place
- recentsArrayList.add(0, newRecent);
+ // remove string if present, so that it doesn't appear multiple times
+ recentsList.remove(newRecent);
+ // put the new value in the first place
+ recentsList.add(0, newRecent);
/*
* 4 because the number of recommended items in App Shortcuts is 4, and also
@@ -999,15 +373,13 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
*/
final int RECENTS_SIZE = 4;
- while (recentsArrayList.size() > RECENTS_SIZE) {
- recentsArrayList.remove(RECENTS_SIZE);
+ while (recentsList.size() > RECENTS_SIZE) {
+ recentsList.remove(RECENTS_SIZE);
}
- //switch to Set, so that it could be inserted into prefs
- recentsSet = new HashSet<String>(recentsArrayList);
-
- prefs.edit().putStringSet(RECENT_DOCUMENTS_KEY, recentsSet).apply();
-
+ // serialize to String that can be set for pref
+ String value = TextUtils.join(RECENT_DOCUMENTS_DELIMITER, recentsList);
+ prefs.edit().putString(RECENT_DOCUMENTS_KEY, value).apply();
//update app shortcuts (7.0 and above)
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) {
@@ -1016,12 +388,17 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
//Remove all shortcuts, and apply new ones.
shortcutManager.removeAllDynamicShortcuts();
- ArrayList<ShortcutInfo> shortcuts = new ArrayList<ShortcutInfo>();
- for (String pathString : recentsArrayList) {
+ ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
+ for (String recentDoc : recentsList) {
+ Uri docUri = Uri.parse(recentDoc);
+ String filename = FileUtilities.retrieveDisplayNameForDocumentUri(getContentResolver(), docUri);
+ if (filename.isEmpty()) {
+ continue;
+ }
//find the appropriate drawable
int drawable = 0;
- switch (FileUtilities.getType(pathString)) {
+ switch (FileUtilities.getType(filename)) {
case FileUtilities.DOC:
drawable = R.drawable.writer;
break;
@@ -1036,12 +413,7 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
break;
}
- File file = new File(pathString);
-
- //for some reason, getName uses %20 instead of space
- String filename = file.getName().replace("%20", " ");
-
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.fromFile(file));
+ Intent intent = new Intent(Intent.ACTION_VIEW, docUri);
String packageName = this.getApplicationContext().getPackageName();
ComponentName componentName = new ComponentName(packageName, LibreOfficeMainActivity.class.getName());
intent.setComponent(componentName);
@@ -1062,161 +434,22 @@ public class LibreOfficeUIActivity extends AppCompatActivity implements Settings
@Override
public void onClick(View v) {
int id = v.getId();
- switch (id){
- case R.id.editFAB:
- if (isFabMenuOpen) {
- collapseFabMenu();
- } else {
- expandFabMenu();
- }
- break;
- case R.id.newWriterFAB:
- createNewFileInputDialog(getString(R.string.default_document_name) + FileUtilities.DEFAULT_WRITER_EXTENSION, NEW_WRITER_STRING_KEY);
- break;
- case R.id.newImpressFAB:
- createNewFileInputDialog(getString(R.string.default_document_name) + FileUtilities.DEFAULT_IMPRESS_EXTENSION, NEW_IMPRESS_STRING_KEY);
- break;
- case R.id.newCalcFAB:
- createNewFileInputDialog(getString(R.string.default_document_name) + FileUtilities.DEFAULT_SPREADSHEET_EXTENSION, NEW_CALC_STRING_KEY);
- break;
- case R.id.newDrawFAB:
- createNewFileInputDialog(getString(R.string.default_document_name) + FileUtilities.DEFAULT_DRAWING_EXTENSION, NEW_DRAW_STRING_KEY);
- break;
- }
- }
-
-
- class ExplorerItemAdapter extends RecyclerView.Adapter<ExplorerItemAdapter.ViewHolder> {
-
- private Activity mActivity;
- private List<IFile> filePaths;
- private final long KB = 1024;
- private final long MB = 1048576;
-
- ExplorerItemAdapter(Activity activity, List<IFile> filePaths) {
- this.mActivity = activity;
- this.filePaths = filePaths;
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- View item = LayoutInflater.from(parent.getContext())
- .inflate(isViewModeList() ? R.layout.file_list_item : R.layout.file_explorer_grid_item, parent, false);
- return new ViewHolder(item);
- }
-
- @Override
- public void onBindViewHolder(final ViewHolder holder, final int position) {
- final IFile file = filePaths.get(position);
-
- holder.itemView.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- open(holder.getAdapterPosition());
- }
- });
- holder.itemView.setOnLongClickListener(new OnLongClickListener() {
-
- @Override
- public boolean onLongClick(View view) {
- //to be picked out by floating context menu (workaround-ish)
- currentlySelectedFile = holder.getAdapterPosition();
- //must return false so the click is not consumed
- return false;
- }
- });
-
- holder.filenameView.setText(file.getName());
- switch (FileUtilities.getType(file.getName())) {
- case FileUtilities.DOC:
- holder.iconView.setImageResource(R.drawable.writer);
- break;
- case FileUtilities.CALC:
- holder.iconView.setImageResource(R.drawable.calc);
- break;
- case FileUtilities.DRAWING:
- holder.iconView.setImageResource(R.drawable.draw);
- break;
- case FileUtilities.IMPRESS:
- holder.iconView.setImageResource(R.drawable.impress);
- break;
- }
-
- if (file.isDirectory()) {
- //Eventually have thumbnails of each sub file on a black circle
- //For now just a folder icon
- holder.iconView.setImageResource(R.drawable.ic_folder_black_24dp);
- holder.iconView.setColorFilter(ContextCompat.getColor(mActivity, R.color.text_color_secondary));
- }
-
- // Date and Size field only exist when we are displaying items in a list.
- if(isViewModeList()) {
- if (!file.isDirectory()) {
- String size;
- long length = filePaths.get(position).getSize();
- if (length < KB) {
- size = Long.toString(length) + "B";
- } else if (length < MB) {
- size = Long.toString(length / KB) + "KB";
- } else {
- size = Long.toString(length / MB) + "MB";
- }
- holder.fileSizeView.setText(size);
- }
- SimpleDateFormat df = new SimpleDateFormat("dd MMM yyyy hh:ss");
- Date date = file.getLastModified();
- //TODO format date
- holder.fileDateView.setText(df.format(date));
- }
- }
-
- @Override
- public int getItemCount() {
- return filePaths.size();
- }
-
- class ViewHolder extends RecyclerView.ViewHolder {
-
- View itemView;
- TextView filenameView, fileSizeView, fileDateView;
- ImageView iconView;
-
- ViewHolder(View itemView) {
- super(itemView);
- this.itemView = itemView;
- filenameView = itemView.findViewById(R.id.file_item_name);
- iconView = itemView.findViewById(R.id.file_item_icon);
- // Check if view mode is List, only then initialise Size and Date field
- if (isViewModeList()) {
- fileSizeView = itemView.findViewById(R.id.file_item_size);
- fileDateView = itemView.findViewById(R.id.file_item_date);
- }
- }
- }
- }
-
- private void setEditFABVisibility(final int visibility){
- LOKitShell.getMainHandler().post(new Runnable() {
- @Override
- public void run() {
- editFAB.setVisibility(visibility);
- }
- });
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- switch(requestCode){
- case PERMISSION_WRITE_EXTERNAL_STORAGE:
- if(permissions.length>0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
- switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
- setEditFABVisibility(View.VISIBLE);
- } else {
- setEditFABVisibility(View.INVISIBLE);
- }
- break;
- default:
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ if (id == R.id.editFAB) {
+ if (isFabMenuOpen) {
+ collapseFabMenu();
+ } else {
+ expandFabMenu();
+ }
+ } else if (id == R.id.open_file_button) {
+ showSystemFilePickerAndOpenFile();
+ } else if (id == R.id.newWriterFAB) {
+ loadNewDocument(DocumentType.WRITER);
+ } else if (id == R.id.newImpressFAB) {
+ loadNewDocument(DocumentType.IMPRESS);
+ } else if (id == R.id.newCalcFAB) {
+ loadNewDocument(DocumentType.CALC);
+ } else if (id == R.id.newDrawFAB) {
+ loadNewDocument(DocumentType.DRAW);
}
}
}
diff --git a/android/source/src/java/org/libreoffice/ui/PageView.java b/android/source/src/java/org/libreoffice/ui/PageView.java
index 1d32a7de7e80..4c3f69562250 100644
--- a/android/source/src/java/org/libreoffice/ui/PageView.java
+++ b/android/source/src/java/org/libreoffice/ui/PageView.java
@@ -17,29 +17,29 @@ import android.view.View;
public class PageView extends View{
private Bitmap bmp;
private Paint mPaintBlack;
- private String tag = "PageView";
+ private static final String LOGTAG = "PageView";
public PageView(Context context ) {
super(context);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);
- intialise();
+ initialise();
}
public PageView(Context context, AttributeSet attrs) {
super(context, attrs);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);
- Log.d( tag , bmp.toString());
- intialise();
+ Log.d(LOGTAG, bmp.toString());
+ initialise();
}
public PageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.dummy_page);//load a "page"
- intialise();
+ initialise();
}
- private void intialise(){
+ private void initialise(){
mPaintBlack = new Paint();
mPaintBlack.setARGB(255, 0, 0, 0);
- Log.d(tag, " Doing some set-up");
+ Log.d(LOGTAG, " Doing some set-up");
}
public void setBitmap(Bitmap bmp){
@@ -49,8 +49,8 @@ public class PageView extends View{
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
- Log.d(tag, "Draw");
- Log.d(tag, Integer.toString(bmp.getHeight()));
+ Log.d(LOGTAG, "Draw");
+ Log.d(LOGTAG, Integer.toString(bmp.getHeight()));
if( bmp != null ){
int horizontalMargin = (int) (canvas.getWidth()*0.1);
//int verticalMargin = (int) (canvas.getHeight()*0.1);
diff --git a/android/source/src/java/org/libreoffice/ui/RecentFile.java b/android/source/src/java/org/libreoffice/ui/RecentFile.java
new file mode 100644
index 000000000000..fdcc688aa140
--- /dev/null
+++ b/android/source/src/java/org/libreoffice/ui/RecentFile.java
@@ -0,0 +1,25 @@
+package org.libreoffice.ui;
+
+import android.net.Uri;
+
+/**
+ * An entry for a recently used file in the RecentFilesAdapter.
+ */
+public class RecentFile {
+
+ private final Uri uri;
+ private final String displayName;
+
+ public RecentFile(Uri docUri, String name) {
+ uri = docUri;
+ displayName = name;
+ }
+
+ public Uri getUri() {
+ return uri;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+}
diff --git a/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java
index fc16d06a48d7..ef00b9fb6cfd 100644
--- a/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java
+++ b/android/source/src/java/org/libreoffice/ui/RecentFilesAdapter.java
@@ -9,8 +9,8 @@
package org.libreoffice.ui;
-import android.support.v4.content.ContextCompat;
-import android.support.v7.widget.RecyclerView;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -18,16 +18,15 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.libreoffice.R;
-import org.libreoffice.storage.IFile;
import java.util.List;
class RecentFilesAdapter extends RecyclerView.Adapter<RecentFilesAdapter.ViewHolder> {
- private LibreOfficeUIActivity mActivity;
- private List<IFile> recentFiles;
+ private final LibreOfficeUIActivity mActivity;
+ private final List<RecentFile> recentFiles;
- RecentFilesAdapter(LibreOfficeUIActivity activity, List<IFile> recentFiles) {
+ RecentFilesAdapter(LibreOfficeUIActivity activity, List<RecentFile> recentFiles) {
this.mActivity = activity;
this.recentFiles = recentFiles;
}
@@ -41,17 +40,16 @@ class RecentFilesAdapter extends RecyclerView.Adapter<RecentFilesAdapter.ViewHol
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
- final IFile iFile = recentFiles.get(position);
+ final RecentFile entry = recentFiles.get(position);
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- mActivity.open(iFile);
+ mActivity.openDocument(entry.getUri());
}
});
- String filename = iFile.getName();
-
+ final String filename = entry.getDisplayName();
holder.textView.setText(filename);
int compoundDrawableInt = 0;
diff --git a/android/source/src/java/org/mozilla/gecko/ZoomConstraints.java b/android/source/src/java/org/mozilla/gecko/ZoomConstraints.java
index f1672ba3dd76..dbe278827279 100644
--- a/android/source/src/java/org/mozilla/gecko/ZoomConstraints.java
+++ b/android/source/src/java/org/mozilla/gecko/ZoomConstraints.java
@@ -6,28 +6,16 @@
package org.mozilla.gecko;
public final class ZoomConstraints {
- private final boolean mAllowZoom;
- private final boolean mAllowDoubleTapZoom;
private final float mDefaultZoom;
private final float mMinZoom;
private final float mMaxZoom;
- public ZoomConstraints(boolean allowZoom, float defaultZoom, float minZoom, float maxZoom) {
- mAllowZoom = allowZoom;
- mAllowDoubleTapZoom = allowZoom;
+ public ZoomConstraints(float defaultZoom, float minZoom, float maxZoom) {
mDefaultZoom = defaultZoom;
mMinZoom = minZoom;
mMaxZoom = maxZoom;
}
- public final boolean getAllowZoom() {
- return mAllowZoom;
- }
-
- public final boolean getAllowDoubleTapZoom() {
- return mAllowDoubleTapZoom;
- }
-
public final float getDefaultZoom() {
return mDefaultZoom;
}
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/GLController.java b/android/source/src/java/org/mozilla/gecko/gfx/GLController.java
index e296f4760f68..6a43dd6a87db 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/GLController.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/GLController.java
@@ -20,7 +20,6 @@ public class GLController {
private LayerView mView;
private int mGLVersion;
- private boolean mSurfaceValid;
private int mWidth, mHeight;
private EGL10 mEGL;
@@ -29,8 +28,6 @@ public class GLController {
private EGLContext mEGLContext;
private EGLSurface mEGLSurface;
- private GL mGL;
-
private static final int LOCAL_EGL_OPENGL_ES2_BIT = 4;
private static final int[] CONFIG_SPEC = {
@@ -45,7 +42,6 @@ public class GLController {
public GLController(LayerView view) {
mView = view;
mGLVersion = 2;
- mSurfaceValid = false;
}
public void setGLVersion(int version) {
@@ -84,12 +80,11 @@ public class GLController {
getEGLError());
}
- mGL = null;
mEGLContext = null;
}
}
- public GL getGL() { return mEGLContext.getGL(); }
+ public GL10 getGL() { return (GL10) mEGLContext.getGL(); }
public EGLDisplay getEGLDisplay() { return mEGLDisplay; }
public EGLConfig getEGLConfig() { return mEGLConfig; }
public EGLContext getEGLContext() { return mEGLContext; }
@@ -104,38 +99,6 @@ public class GLController {
return mEGL.eglSwapBuffers(mEGLDisplay, mEGLSurface);
}
- public boolean checkForLostContext() {
- if (mEGL.eglGetError() != EGL11.EGL_CONTEXT_LOST) {
- return false;
- }
-
- mEGLDisplay = null;
- mEGLConfig = null;
- mEGLContext = null;
- mEGLSurface = null;
- mGL = null;
- return true;
- }
-
- // This function is invoked by JNI
- public synchronized void resumeCompositorIfValid() {
- if (mSurfaceValid) {
- mView.getListener().compositionResumeRequested(mWidth, mHeight);
- }
- }
-
- // Wait until we are allowed to use EGL functions on the Surface backing
- // this window. This function is invoked by JNI
- public synchronized void waitForValidSurface() {
- while (!mSurfaceValid) {
- try {
- wait();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
public synchronized int getWidth() {
return mWidth;
}
@@ -145,14 +108,12 @@ public class GLController {
}
synchronized void surfaceDestroyed() {
- mSurfaceValid = false;
notifyAll();
}
synchronized void surfaceChanged(int newWidth, int newHeight) {
mWidth = newWidth;
mHeight = newHeight;
- mSurfaceValid = true;
notifyAll();
}
@@ -183,11 +144,10 @@ public class GLController {
getEGLError());
}
- mGL = mEGLContext.getGL();
-
if (mView.getRenderer() != null) {
- mView.getRenderer().onSurfaceCreated((GL10)mGL, mEGLConfig);
- mView.getRenderer().onSurfaceChanged((GL10)mGL, mWidth, mHeight);
+ GL10 gl = (GL10) mEGLContext.getGL();
+ mView.getRenderer().onSurfaceCreated(gl, mEGLConfig);
+ mView.getRenderer().onSurfaceChanged(gl, mWidth, mHeight);
}
}
@@ -216,7 +176,8 @@ public class GLController {
}
}
- throw new GLControllerException("No suitable EGL configuration found");
+ // if there's no 565 RGB configuration, select another one that fulfils the specification
+ return configs[0];
}
private void createEGLSurface() {
@@ -232,32 +193,11 @@ public class GLController {
"surface! " + getEGLError());
}
- mGL = mEGLContext.getGL();
-
if (mView.getRenderer() != null) {
- mView.getRenderer().onSurfaceCreated((GL10)mGL, mEGLConfig);
- mView.getRenderer().onSurfaceChanged((GL10)mGL, mView.getWidth(), mView.getHeight());
- }
- }
-
- /**
- * Provides an EGLSurface without assuming ownership of this surface.
- * This class does not keep a reference to the provided EGL surface; the
- * caller assumes ownership of the surface once it is returned.
- */
- private EGLSurface provideEGLSurface() {
- if (mEGL == null) {
- initEGL();
+ GL10 gl = (GL10) mEGLContext.getGL();
+ mView.getRenderer().onSurfaceCreated(gl, mEGLConfig);
+ mView.getRenderer().onSurfaceChanged(gl, mView.getWidth(), mView.getHeight());
}
-
- Object window = mView.getNativeWindow();
- EGLSurface surface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, window, null);
- if (surface == null || surface == EGL10.EGL_NO_SURFACE) {
- throw new GLControllerException("EGL window surface could not be created! " +
- getEGLError());
- }
-
- return surface;
}
private String getEGLError() {
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
index 681fb6fd6019..72a96f0bb00f 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java
@@ -80,7 +80,7 @@ public class GeckoLayerClient implements PanZoomTarget {
mView.setLayerRenderer(mLayerRenderer);
- sendResizeEventIfNecessary();
+ sendResizeEventIfNecessary(false);
mView.requestRender();
}
@@ -124,21 +124,23 @@ public class GeckoLayerClient implements PanZoomTarget {
* to the layer client. That way, the layer client won't be tempted to call this, which might
* result in an infinite loop.
*/
- void setViewportSize(FloatSize size) {
+ void setViewportSize(FloatSize size, boolean forceResizeEvent) {
mViewportMetrics = mViewportMetrics.setViewportSize(size.width, size.height);
- sendResizeEventIfNecessary();
+ sendResizeEventIfNecessary(forceResizeEvent);
}
PanZoomController getPanZoomController() {
return mPanZoomController;
}
- /* Informs Gecko that the screen size has changed. */
- private void sendResizeEventIfNecessary() {
+ /* Informs Gecko that the screen size has changed.
+ * @param force: If true, a resize event will always be sent, otherwise
+ * it is only sent if size has changed. */
+ private void sendResizeEventIfNecessary(boolean force) {
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
IntSize newScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
- if (mScreenSize.equals(newScreenSize)) {
+ if (!force && mScreenSize.equals(newScreenSize)) {
return;
}
@@ -233,7 +235,7 @@ public class GeckoLayerClient implements PanZoomTarget {
}
private void geometryChanged() {
- sendResizeEventIfNecessary();
+ sendResizeEventIfNecessary(false);
if (getRedrawHint()) {
adjustViewport(null);
}
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java b/android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
index db2fcc03c5b3..b20d602a21cb 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/JavaPanZoomController.java
@@ -21,6 +21,7 @@ import org.mozilla.gecko.util.FloatUtils;
import java.util.Timer;
import java.util.TimerTask;
+import java.lang.StrictMath;
/*
* Handles the kinetic scrolling and zooming physics for a layer controller.
@@ -143,16 +144,9 @@ class JavaPanZoomController
/** This function MUST be called on the UI thread */
public boolean onMotionEvent(MotionEvent event) {
- if (Build.VERSION.SDK_INT <= 11) {
- return false;
- }
-
- switch (event.getSource() & InputDevice.SOURCE_CLASS_MASK) {
- case InputDevice.SOURCE_CLASS_POINTER:
- switch (event.getAction() & MotionEvent.ACTION_MASK) {
- case MotionEvent.ACTION_SCROLL: return handlePointerScroll(event);
- }
- break;
+ if ((event.getSource() & InputDevice.SOURCE_CLASS_MASK) == InputDevice.SOURCE_CLASS_POINTER
+ && (event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_SCROLL) {
+ return handlePointerScroll(event);
}
return false;
}
@@ -433,7 +427,7 @@ class JavaPanZoomController
private float panDistance(MotionEvent move) {
float dx = mX.panDistance(move.getX(0));
float dy = mY.panDistance(move.getY(0));
- return (float) Math.sqrt(dx * dx + dy * dy);
+ return (float) Math.hypot(dx , dy);
}
private void track(float x, float y, long time) {
@@ -550,7 +544,7 @@ class JavaPanZoomController
private float getVelocity() {
float xvel = mX.getRealVelocity();
float yvel = mY.getRealVelocity();
- return (float) Math.sqrt(xvel * xvel + yvel * yvel);
+ return (float) StrictMath.hypot(xvel, yvel);
}
public PointF getVelocityVector() {
@@ -751,11 +745,6 @@ class JavaPanZoomController
if (constraints.getMaxZoom() > 0)
maxZoomFactor = constraints.getMaxZoom();
- if (!constraints.getAllowZoom()) {
- // If allowZoom is false, clamp to the default zoom level.
- maxZoomFactor = minZoomFactor = constraints.getDefaultZoom();
- }
-
maxZoomFactor = Math.max(maxZoomFactor, minZoomFactor);
if (zoomFactor < minZoomFactor) {
@@ -828,7 +817,7 @@ class JavaPanZoomController
if (mState == PanZoomState.ANIMATED_ZOOM)
return false;
- if (null == mTarget.getZoomConstraints() || !mTarget.getZoomConstraints().getAllowZoom())
+ if (null == mTarget.getZoomConstraints())
return false;
setState(PanZoomState.PINCHING);
@@ -934,10 +923,7 @@ class JavaPanZoomController
@Override
public boolean onDown(MotionEvent motionEvent) {
- if (mTarget.getZoomConstraints() != null)
- mWaitForDoubleTap = mTarget.getZoomConstraints().getAllowDoubleTapZoom();
- else
- mWaitForDoubleTap = false;
+ mWaitForDoubleTap = mTarget.getZoomConstraints() != null;
return false;
}
@@ -991,14 +977,14 @@ class JavaPanZoomController
@Override
public boolean onDoubleTap(MotionEvent motionEvent) {
- if (null == mTarget.getZoomConstraints() || !mTarget.getZoomConstraints().getAllowDoubleTapZoom()) {
+ if (null == mTarget.getZoomConstraints()) {
return true;
}
// Double tap zooms in or out depending on the current zoom factor
PointF pointOfTap = getMotionInDocumentCoordinates(motionEvent);
ImmutableViewportMetrics metrics = getMetrics();
float newZoom = metrics.getZoomFactor() >=
- DOUBLE_TAP_THRESHOLD ? mTarget.getZoomConstraints().getMinZoom() : DOUBLE_TAP_THRESHOLD;
+ DOUBLE_TAP_THRESHOLD ? mTarget.getZoomConstraints().getDefaultZoom() : DOUBLE_TAP_THRESHOLD;
// calculate new top_left point from the point of tap
float ratio = newZoom/metrics.getZoomFactor();
float newLeft = pointOfTap.x - 1/ratio * (pointOfTap.x - metrics.getOrigin().x / metrics.getZoomFactor());
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java b/android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
index b1aea3616d6c..6ea7dd0edc10 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/LayerRenderer.java
@@ -48,13 +48,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
private FloatBuffer mCoordBuffer;
private RenderContext mLastPageContext;
private int mMaxTextureSize;
- private int mBackgroundColor;
private CopyOnWriteArrayList<Layer> mExtraLayers = new CopyOnWriteArrayList<Layer>();
- /* Used by robocop for testing purposes */
- private IntBuffer mPixelBuffer;
-
// Used by GLES 2.0
private int mProgram;
private int mPositionHandle;
@@ -146,6 +142,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
mVertScrollLayer.destroy();
}
+ @Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
createDefaultProgram();
activateDefaultProgram();
@@ -184,9 +181,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
GLES20.glEnableVertexAttribArray(mTextureHandle);
GLES20.glUniform1i(mSampleHandle, 0);
-
- // TODO: Move these calls into a separate deactivate() call that is called after the
- // underlay and overlay are rendered.
}
// Deactivates the shader program. This must be done to avoid crashes after returning to the
@@ -220,8 +214,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
/**
* Called whenever a new frame is about to be drawn.
*/
+ @Override
public void onDrawFrame(GL10 gl) {
- Frame frame = createFrame(mView.getLayerClient().getViewportMetrics());
+ Frame frame = new Frame(mView.getLayerClient().getViewportMetrics());
synchronized (mView.getLayerClient()) {
frame.beginDrawing();
frame.drawBackground();
@@ -249,6 +244,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
mCoordBuffer);
}
+ @Override
public void onSurfaceChanged(GL10 gl, final int width, final int height) {
GLES20.glViewport(0, 0, width, height);
}
@@ -264,10 +260,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
return shader;
}
- public Frame createFrame(ImmutableViewportMetrics metrics) {
- return new Frame(metrics);
- }
-
class FadeRunnable implements Runnable {
private boolean mStarted;
private long mRunAt;
@@ -305,8 +297,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
}
public class Frame {
- // The timestamp recording the start of this frame.
- private long mFrameStartTime;
// A fixed snapshot of the viewport metrics that this frame is using to render content.
private ImmutableViewportMetrics mFrameMetrics;
// A rendering context for page-positioned layers, and one for screen-positioned layers.
@@ -348,10 +338,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
return pageRect;
}
- /** This function is invoked via JNI; be careful when modifying signature. */
public void beginDrawing() {
- mFrameStartTime = SystemClock.uptimeMillis();
-
TextureReaper.get().reap();
TextureGenerator.get().fill();
@@ -386,58 +373,18 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
mUpdated &= layer.update(mPageContext); // called on compositor thread
}
- /** Retrieves the bounds for the layer, rounded in such a way that it
- * can be used as a mask for something that will render underneath it.
- * This will round the bounds inwards, but stretch the mask towards any
- * near page edge, where near is considered to be 'within 2 pixels'.
- * Returns null if the given layer is null.
- */
- private Rect getMaskForLayer(Layer layer) {
- if (layer == null) {
- return null;
- }
-
- RectF bounds = RectUtils.contract(layer.getBounds(mPageContext), 1.0f, 1.0f);
- Rect mask = RectUtils.roundIn(bounds);
-
- // If the mask is within two pixels of any page edge, stretch it over
- // that edge. This is to avoid drawing thin slivers when masking
- // layers.
- if (mask.top <= 2) {
- mask.top = -1;
- }
- if (mask.left <= 2) {
- mask.left = -1;
- }
-
- // Because we're drawing relative to the page-rect, we only need to
- // take into account its width and height (and not its origin)
- int pageRight = mPageRect.width();
- int pageBottom = mPageRect.height();
-
- if (mask.right >= pageRight - 2) {
- mask.right = pageRight + 1;
- }
- if (mask.bottom >= pageBottom - 2) {
- mask.bottom = pageBottom + 1;
- }
-
- return mask;
- }
-
- /** This function is invoked via JNI; be careful when modifying signature. */
public void drawBackground() {
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
/* Update background color. */
- mBackgroundColor = Color.WHITE;
+ final int backgroundColor = Color.WHITE;
/* Clear to the page background colour. The bits set here need to
* match up with those used in gfx/layers/opengl/LayerManagerOGL.cpp.
*/
- GLES20.glClearColor(((mBackgroundColor>>16)&0xFF) / 255.0f,
- ((mBackgroundColor>>8)&0xFF) / 255.0f,
- (mBackgroundColor&0xFF) / 255.0f,
+ GLES20.glClearColor(((backgroundColor >> 16) & 0xFF) / 255.0f,
+ ((backgroundColor >> 8) & 0xFF) / 255.0f,
+ (backgroundColor & 0xFF) / 255.0f,
0.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT |
GLES20.GL_DEPTH_BUFFER_BIT);
@@ -474,7 +421,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
rootLayer.draw(mPageContext);
}
- /** This function is invoked via JNI; be careful when modifying signature. */
public void drawForeground() {
/* Draw any extra layers that were added (likely plugins) */
if (mExtraLayers.size() > 0) {
@@ -498,23 +444,10 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
mHorizScrollLayer.draw(mPageContext);
}
- /** This function is invoked via JNI; be careful when modifying signature. */
public void endDrawing() {
// If a layer update requires further work, schedule another redraw
if (!mUpdated)
mView.requestRender();
-
- /* Used by robocop for testing purposes */
- IntBuffer pixelBuffer = mPixelBuffer;
- if (mUpdated && pixelBuffer != null) {
- synchronized (pixelBuffer) {
- pixelBuffer.position(0);
- GLES20.glReadPixels(0, 0, (int)mScreenContext.viewport.width(),
- (int)mScreenContext.viewport.height(), GLES20.GL_RGBA,
- GLES20.GL_UNSIGNED_BYTE, pixelBuffer);
- pixelBuffer.notify();
- }
- }
}
}
}
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/source/src/java/org/mozilla/gecko/gfx/LayerView.java
index 05f2118114c8..29049f92912d 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/LayerView.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/LayerView.java
@@ -11,14 +11,12 @@ import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
-import android.graphics.SurfaceTexture;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
-import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
@@ -37,8 +35,6 @@ import org.mozilla.gecko.OnSlideSwipeListener;
*
* This view delegates to LayerRenderer to actually do the drawing. Its role is largely that of a
* mediator between the LayerRenderer and the LayerController.
- *
- * Note that LayerView is accessed by Robocop via reflection.
*/
public class LayerView extends FrameLayout {
private static String LOGTAG = LayerView.class.getName();
@@ -49,59 +45,22 @@ public class LayerView extends FrameLayout {
private InputConnectionHandler mInputConnectionHandler;
private LayerRenderer mRenderer;
- /* Must be a PAINT_xxx constant */
- private int mPaintState = PAINT_NONE;
- private boolean mFullScreen = false;
-
private SurfaceView mSurfaceView;
- private TextureView mTextureView;
private Listener mListener;
private OnInterceptTouchListener mTouchIntercepter;
- //TODO static because of registerCxxCompositor() function, should be fixed in the future
- private static LibreOfficeMainActivity mContext;
-
- /* Flags used to determine when to show the painted surface. The integer
- * order must correspond to the order in which these states occur. */
- public static final int PAINT_NONE = 0;
- public static final int PAINT_BEFORE_FIRST = 1;
- public static final int PAINT_AFTER_FIRST = 2;
-
- boolean shouldUseTextureView() {
- // we can only use TextureView on ICS or higher
- /*if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- Log.i(LOGTAG, "Not using TextureView: not on ICS+");
- return false;
- }
-
- try {
- // and then we can only use it if we have a hardware accelerated window
- Method m = View.class.getMethod("isHardwareAccelerated", new Class[0]);
- return (Boolean) m.invoke(this);
- } catch (Exception e) {
- Log.i(LOGTAG, "Not using TextureView: caught exception checking for hw accel: " + e.toString());
- return false;
- }*/
- return false;
- }
+ private LibreOfficeMainActivity mContext;
public LayerView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = (LibreOfficeMainActivity) context;
- if (shouldUseTextureView()) {
- mTextureView = new TextureView(context);
- mTextureView.setSurfaceTextureListener(new SurfaceTextureListener());
+ mSurfaceView = new SurfaceView(context);
+ addView(mSurfaceView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- addView(mTextureView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
- } else {
- mSurfaceView = new SurfaceView(context);
- addView(mSurfaceView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
-
- SurfaceHolder holder = mSurfaceView.getHolder();
- holder.addCallback(new SurfaceListener());
+ SurfaceHolder holder = mSurfaceView.getHolder();
+ holder.addCallback(new SurfaceListener());
holder.setFormat(PixelFormat.RGB_565);
- }
mGLController = new GLController(this);
}
@@ -183,10 +142,6 @@ public class LayerView extends FrameLayout {
public GeckoLayerClient getLayerClient() { return mLayerClient; }
public PanZoomController getPanZoomController() { return mPanZoomController; }
- public void setViewportSize(IntSize size) {
- mLayerClient.setViewportSize(new FloatSize(size));
- }
-
public ImmutableViewportMetrics getViewportMetrics() {
return mLayerClient.getViewportMetrics();
}
@@ -223,13 +178,6 @@ public class LayerView extends FrameLayout {
return mInputConnectionHandler != null && mInputConnectionHandler.onKeyUp(keyCode, event);
}
- public boolean isIMEEnabled() {
- /*if (mInputConnectionHandler != null) {
- return mInputConnectionHandler.isIMEEnabled();
- }*/
- return false;
- }
-
public void requestRender() {
if (mListener != null) {
mListener.renderRequested();
@@ -256,19 +204,6 @@ public class LayerView extends FrameLayout {
return mRenderer;
}
- /* paintState must be a PAINT_xxx constant. The state will only be changed
- * if paintState represents a state that occurs after the current state. */
- public void setPaintState(int paintState) {
- if (paintState > mPaintState) {
- Log.d(LOGTAG, "LayerView paint state set to " + paintState);
- mPaintState = paintState;
- }
- }
-
- public int getPaintState() {
- return mPaintState;
- }
-
public LayerRenderer getRenderer() {
return mRenderer;
}
@@ -306,7 +241,7 @@ public class LayerView extends FrameLayout {
private void onSizeChanged(int width, int height) {
mGLController.surfaceChanged(width, height);
- mLayerClient.setViewportSize(new FloatSize(width, height));
+ mLayerClient.setViewportSize(new FloatSize(width, height), false);
if (mListener != null) {
mListener.surfaceChanged(width, height);
@@ -324,29 +259,13 @@ public class LayerView extends FrameLayout {
}
public Object getNativeWindow() {
- if (mSurfaceView != null)
- return mSurfaceView.getHolder();
-
- return mTextureView.getSurfaceTexture();
- }
-
- /** This function is invoked by Gecko (compositor thread) via JNI; be careful when modifying signature. */
- public static GLController registerCxxCompositor() {
- try {
- LayerView layerView = mContext.getLayerClient().getView();
- layerView.mListener.compositorCreated();
- return layerView.getGLController();
- } catch (Exception e) {
- Log.e(LOGTAG, "Error registering compositor!", e);
- return null;
- }
+ return mSurfaceView.getHolder();
}
public interface Listener {
void compositorCreated();
void renderRequested();
void compositionPauseRequested();
- void compositionResumeRequested(int width, int height);
void surfaceChanged(int width, int height);
}
@@ -371,30 +290,7 @@ public class LayerView extends FrameLayout {
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
- setViewportSize(new IntSize(right - left, bottom - top));
- }
- }
-
- private class SurfaceTextureListener implements TextureView.SurfaceTextureListener {
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- // We don't do this for surfaceCreated above because it is always followed by a surfaceChanged,
- // but that is not the case here.
- if (mRenderControllerThread != null) {
- mRenderControllerThread.surfaceCreated();
- }
- onSizeChanged(width, height);
- }
-
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- onDestroyed();
- return true; // allow Android to call release() on the SurfaceTexture, we are done drawing to it
- }
-
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- onSizeChanged(width, height);
- }
-
- public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ mLayerClient.setViewportSize(new FloatSize(right - left, bottom - top), true);
}
}
@@ -438,12 +334,4 @@ public class LayerView extends FrameLayout {
super(e);
}
}
-
- public void setFullScreen(boolean fullScreen) {
- mFullScreen = fullScreen;
- }
-
- public boolean isFullScreen() {
- return mFullScreen;
- }
}
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java b/android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java
index 4eb07a31f147..4eff380527d2 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/PointUtils.java
@@ -11,6 +11,8 @@ import android.graphics.PointF;
import org.json.JSONException;
import org.json.JSONObject;
+import java.lang.StrictMath;
+
public final class PointUtils {
public static PointF add(PointF one, PointF two) {
return new PointF(one.x + two.x, one.y + two.y);
@@ -30,7 +32,7 @@ public final class PointUtils {
/* Computes the magnitude of the given vector. */
public static float distance(PointF point) {
- return (float)Math.sqrt(point.x * point.x + point.y * point.y);
+ return (float)StrictMath.hypot(point.x, point.y);
}
/** Computes the scalar distance between two points. */
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java b/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java
index 06f82f158366..5c74d56a004b 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/RenderControllerThread.java
@@ -82,11 +82,6 @@ public class RenderControllerThread extends Thread implements LayerView.Listener
}
@Override
- public void compositionResumeRequested(int width, int height) {
-
- }
-
- @Override
public void surfaceChanged(int width, int height) {
this.width = width;
this.height = height;
@@ -115,7 +110,7 @@ public class RenderControllerThread extends Thread implements LayerView.Listener
}
GLSurfaceView.Renderer renderer = getRenderer();
if (renderer != null) {
- renderer.onDrawFrame((GL10) controller.getGL());
+ renderer.onDrawFrame(controller.getGL());
}
controller.swapBuffers();
}
@@ -123,7 +118,7 @@ public class RenderControllerThread extends Thread implements LayerView.Listener
private void doSizeChanged() {
GLSurfaceView.Renderer renderer = getRenderer();
if (renderer != null) {
- renderer.onSurfaceChanged((GL10) controller.getGL(), width, height);
+ renderer.onSurfaceChanged(controller.getGL(), width, height);
}
}
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java b/android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java
index 1d901a02a14b..e89015b5ed8c 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/SimpleScaleGestureDetector.java
@@ -34,7 +34,7 @@ import java.util.Stack;
* - It doesn't take pressure into account, which results in smoother scaling.
*/
public class SimpleScaleGestureDetector {
- private static final String LOGTAG = "GeckoSimpleScaleGestureDetector";
+ private static final String LOGTAG = "ScaleGestureDetector";
private SimpleScaleGestureListener mListener;
private long mLastEventTime;
diff --git a/android/source/src/java/org/mozilla/gecko/gfx/SubTile.java b/android/source/src/java/org/mozilla/gecko/gfx/SubTile.java
index 42750df62838..bdad37195d90 100644
--- a/android/source/src/java/org/mozilla/gecko/gfx/SubTile.java
+++ b/android/source/src/java/org/mozilla/gecko/gfx/SubTile.java
@@ -86,26 +86,24 @@ public class SubTile extends Layer {
protected void finalize() throws Throwable {
try {
destroyImage();
- cleanTexture(false);
+ cleanTexture();
} finally {
super.finalize();
}
}
- private void cleanTexture(boolean immediately) {
+ private void cleanTexture() {
if (mTextureIDs != null) {
TextureReaper.get().add(mTextureIDs);
mTextureIDs = null;
- if (immediately) {
- TextureReaper.get().reap();
- }
+ TextureReaper.get().reap();
}
}
public void destroy() {
try {
destroyImage();
- cleanTexture(false);
+ cleanTexture();
} catch (Exception ex) {
Log.e(LOGTAG, "Error clearing buffers: ", ex);
}
@@ -140,7 +138,7 @@ public class SubTile extends Layer {
if (!textureSize.equals(mSize)) {
mSize = textureSize;
- cleanTexture(true);
+ cleanTexture();
}
}
@@ -253,4 +251,4 @@ public class SubTile extends Layer {
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
}
}
-} \ No newline at end of file
+}