[Libreoffice-commits] core.git: Branch 'feature/owncloud-provider-for-android' - 27 commits - android/experimental chart2/source configure.ac dbaccess/source download.lst external/Module_external.mk external/owncloud-android-lib helpcontent2 Makefile.fetch RepositoryExternal.mk sc/inc sc/source slideshow/source solenv/bin svx/source sw/CppunitTest_sw_macros_test.mk sw/inc sw/qa sw/source sw/uiconfig

Jacobo Aragunde Pérez jaragunde at igalia.com
Fri Feb 13 05:18:09 PST 2015


Rebased ref, commits from common ancestor:
commit 3e72c3e65cc54a59c322956fe014d3a3bac15a27
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue Feb 10 16:17:12 2015 +0000

    Android: improve error handling in ownCloud provider.
    
    This provider now throws exceptions with properly internationalized
    messages to be shown to the user.
    
    Change-Id: I0464bffe14cab24d50180cb5e2e62ce746bcba74

diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index 336b19b..135e52d 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -36,6 +36,10 @@
     <string name="local_file_system">Local file system</string>
     <string name="owncloud">ownCloud</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>
+
     <!-- Document provider settings -->
     <string name="storage_provider_settings">Storage provider settings</string>
     <string name="owncloud_settings">ownCloud settings</string>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
index a8d1a06..ce10ab6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
@@ -69,8 +69,7 @@ public class OwnCloudFile implements IFile {
             RemoteOperationResult result = refreshOperation.execute(provider
                     .getClient());
             if (!result.isSuccess()) {
-                throw new RuntimeException(result.getLogMessage(),
-                        result.getException());
+                throw provider.buildRuntimeExceptionForResultCode(result.getCode());
             }
             for (Object obj : result.getData()) {
                 RemoteFile child = (RemoteFile) obj;
@@ -104,7 +103,10 @@ public class OwnCloudFile implements IFile {
         File downFolder = provider.getCacheDir();
         DownloadRemoteFileOperation operation = new DownloadRemoteFileOperation(
                 file.getRemotePath(), downFolder.getAbsolutePath());
-        operation.execute(provider.getClient());
+        RemoteOperationResult result = operation.execute(provider.getClient());
+        if (!result.isSuccess()) {
+            throw provider.buildRuntimeExceptionForResultCode(result.getCode());
+        }
         return new File(downFolder.getAbsolutePath() + file.getRemotePath());
     }
 
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
index 827c0af..66e4633 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
@@ -18,6 +18,7 @@ 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;
@@ -78,8 +79,7 @@ public class OwnCloudProvider implements IDocumentProvider,
                 uri.getPath());
         RemoteOperationResult result = refreshOperation.execute(client);
         if (!result.isSuccess()) {
-            throw new RuntimeException(result.getLogMessage(),
-                    result.getException());
+            throw buildRuntimeExceptionForResultCode(result.getCode());
         }
         if (result.getData().size() > 0) {
             return new OwnCloudFile(this, (RemoteFile) result.getData().get(0));
@@ -113,6 +113,29 @@ public class OwnCloudProvider implements IDocumentProvider,
     }
 
     /**
+     * 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
commit 9fa0cf26709af7884f30054b1cf50f68d5d2d016
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Mon Feb 9 20:20:11 2015 +0100

    Android: document providers listen to changes in preferences.
    
    With this patch, document providers are able to listen to changes in
    their preferences and update their internal state accordingly. Now
    ownCloud provider can see its server updated without restarting the
    application.
    
    Change-Id: I833c7ec9fc97be58bdc8ac2cbf4384a33c2b400e

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java
index 3d462e6..612eaa6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java
@@ -9,11 +9,15 @@
 
 package org.libreoffice.storage;
 
+import java.util.HashSet;
+import java.util.Set;
+
 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.
@@ -103,4 +107,14 @@ public final class DocumentProviderFactory {
     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/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
index d17fe51..e98534a 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
@@ -9,11 +9,15 @@
 
 package org.libreoffice.storage;
 
+import java.util.Set;
+
 import org.libreoffice.R;
 
 import android.app.Activity;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
 import android.os.Bundle;
 import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
 
 public class DocumentProviderSettingsActivity extends Activity {
 
@@ -21,6 +25,8 @@ public class DocumentProviderSettingsActivity extends Activity {
     public static final String KEY_PREF_OWNCLOUD_USER_NAME = "pref_user_name";
     public static final String KEY_PREF_OWNCLOUD_PASSWORD = "pref_password";
 
+    private Set<OnSharedPreferenceChangeListener> listeners;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -30,6 +36,27 @@ public class DocumentProviderSettingsActivity extends Activity {
                 .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) {
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
index a94e1ad..827c0af 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
@@ -10,6 +10,7 @@ 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;
 
@@ -24,8 +25,10 @@ import com.owncloud.android.lib.resources.files.RemoteFile;
 /**
  * Implementation of IDocumentProvider for ownCloud servers.
  */
-public class OwnCloudProvider implements IDocumentProvider {
+public class OwnCloudProvider implements IDocumentProvider,
+        OnSharedPreferenceChangeListener {
 
+    private Context context;
     private OwnCloudClient client;
     private File cacheDir;
 
@@ -34,6 +37,8 @@ public class OwnCloudProvider implements IDocumentProvider {
     private String password;
 
     public OwnCloudProvider(Context context) {
+        this.context = context;
+
         // read preferences
         SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
         serverUrl = preferences.getString(
@@ -43,11 +48,7 @@ public class OwnCloudProvider implements IDocumentProvider {
         password = preferences.getString(
                 DocumentProviderSettingsActivity.KEY_PREF_OWNCLOUD_PASSWORD, "");
 
-        Uri serverUri = Uri.parse(serverUrl);
-        client = OwnCloudClientFactory.createOwnCloudClient(serverUri,
-                context, true);
-        client.setCredentials(OwnCloudCredentialsFactory.newBasicCredentials(
-                userName, password));
+        setupClient();
 
         // make sure cache directory exists, and clear it
         // TODO: probably we should do smarter cache management
@@ -58,6 +59,14 @@ public class OwnCloudProvider implements IDocumentProvider {
         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() {
         return createFromUri(URI.create(FileUtils.PATH_SEPARATOR));
@@ -116,4 +125,25 @@ public class OwnCloudProvider implements IDocumentProvider {
         }
         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();
+    }
 }
commit c228f26b138f4a0122ccec9b8d016fdd53fa700a
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Mon Feb 9 14:10:29 2015 +0100

    Android: add menu entry for document provider settings
    
    Change-Id: Ic48275fe2e7d83fd5e77171f4f5740a527dec7e2

diff --git a/android/experimental/LOAndroid3/res/menu/view_menu.xml b/android/experimental/LOAndroid3/res/menu/view_menu.xml
index f316f5a..aff3709 100644
--- a/android/experimental/LOAndroid3/res/menu/view_menu.xml
+++ b/android/experimental/LOAndroid3/res/menu/view_menu.xml
@@ -11,6 +11,8 @@
           android:title="@string/menu_sort_az"/>
     <item android:id="@+id/menu_sort_modified"
           android:title="@string/menu_sort_modified"/>
+    <item android:id="@+id/menu_storage_preferences"
+          android:title="@string/storage_provider_settings"/>
     <item android:id="@+id/action_about"
           android:title="@string/action_about"
           android:orderInCategory="100"/>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index 0457723..2a4b69f 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -13,6 +13,7 @@ import org.libreoffice.LibreOfficeMainActivity;
 import org.libreoffice.R;
 import org.libreoffice.LOAbout;
 import org.libreoffice.storage.DocumentProviderFactory;
+import org.libreoffice.storage.DocumentProviderSettingsActivity;
 import org.libreoffice.storage.IDocumentProvider;
 import org.libreoffice.storage.IFile;
 import org.libreoffice.storage.local.LocalDocumentsProvider;
@@ -444,6 +445,10 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
             case R.id.action_about:
                 showAbout();
                 return true;
+        case R.id.menu_storage_preferences:
+            startActivity(new Intent(this, DocumentProviderSettingsActivity.class));;
+            break;
+
             default:
                 return super.onOptionsItemSelected(item);
         }
commit ce6be12d2158125add944df74a105316cdb03833
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Mon Feb 9 14:04:59 2015 +0100

    Android: setup ownCloud provider with user-defined settings
    
    Change-Id: I4ad4dd12854ca9f332055a50131959f60f7da504

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
index bb04855..d17fe51 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
@@ -16,6 +16,11 @@ import android.os.Bundle;
 import android.preference.PreferenceFragment;
 
 public class DocumentProviderSettingsActivity extends Activity {
+
+    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";
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
index db2b698..a94e1ad 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
@@ -4,11 +4,14 @@ 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.net.Uri;
+import android.preference.PreferenceManager;
 
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.OwnCloudClientFactory;
@@ -26,12 +29,20 @@ public class OwnCloudProvider implements IDocumentProvider {
     private OwnCloudClient client;
     private File cacheDir;
 
-    // TODO: these must be configurable
-    final private String serverUrl = "http://10.0.2.2/owncloud"; //emulator host machine
-    final private String userName = "admin";
-    final private String password = "admin";
+    private String serverUrl;
+    private String userName;
+    private String password;
 
     public OwnCloudProvider(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, "");
+
         Uri serverUri = Uri.parse(serverUrl);
         client = OwnCloudClientFactory.createOwnCloudClient(serverUri,
                 context, true);
commit 5621c5619fc1c5cb9cd09cf2aa46ef9ea508cd3e
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Mon Feb 9 12:37:46 2015 +0100

    Android: settings activity for document providers
    
    Creates an activity to manage the settings of any document provider
    that needs them, and populated it with the settings required by the
    ownCloud implementation.
    
    The settings screen is not yet plugged to the document browser UI but
    can be launched with this command:
    
      adb shell am start -a android.intent.action.MAIN \
      -n org.libreoffice/.storage.DocumentProviderSettingsActivity
    
    Change-Id: I83cff641fa61078f2bddbb98262af989c06985a9

diff --git a/android/experimental/LOAndroid3/AndroidManifest.xml.in b/android/experimental/LOAndroid3/AndroidManifest.xml.in
index cc61db5..fc6958b 100644
--- a/android/experimental/LOAndroid3/AndroidManifest.xml.in
+++ b/android/experimental/LOAndroid3/AndroidManifest.xml.in
@@ -99,6 +99,14 @@
             </intent-filter>
         </activity>
 
+        <!-- Document Provider Settings Activity -->
+        <activity android:name=".storage.DocumentProviderSettingsActivity"
+                  android:label="@string/storage_provider_settings">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+
     </application>
 
 </manifest>
diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index 50cd31e..336b19b 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -36,4 +36,12 @@
     <string name="local_file_system">Local file system</string>
     <string name="owncloud">ownCloud</string>
 
+    <!-- Document provider settings -->
+    <string name="storage_provider_settings">Storage provider settings</string>
+    <string name="owncloud_settings">ownCloud settings</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="password">Password</string>
+
 </resources>
diff --git a/android/experimental/LOAndroid3/res/xml/documentprovider_preferences.xml b/android/experimental/LOAndroid3/res/xml/documentprovider_preferences.xml
new file mode 100644
index 0000000..a359d14
--- /dev/null
+++ b/android/experimental/LOAndroid3/res/xml/documentprovider_preferences.xml
@@ -0,0 +1,26 @@
+<?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:defaultValue="http://" />
+        <EditTextPreference
+            android:key="pref_user_name"
+            android:title="@string/user_name"
+            android:defaultValue="" />
+        <EditTextPreference
+            android:key="pref_password"
+            android:title="@string/password"
+            android:defaultValue="" />
+    </PreferenceCategory>
+</PreferenceScreen>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
new file mode 100644
index 0000000..bb04855
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderSettingsActivity.java
@@ -0,0 +1,37 @@
+/* -*- 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 org.libreoffice.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+public class DocumentProviderSettingsActivity extends Activity {
+    @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();
+    }
+
+    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);
+        }
+    }
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
index 9435c092..0457723 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/ui/LibreOfficeUIActivity.java
@@ -112,6 +112,8 @@ public class LibreOfficeUIActivity extends LOAbout implements ActionBar.OnNaviga
         DocumentProviderFactory.initialize(this);
         documentProviderFactory = DocumentProviderFactory.getInstance();
 
+        PreferenceManager.setDefaultValues(this, R.xml.documentprovider_preferences, false);
+
         // init UI and populate with contents from the provider
         createUI();
         switchToDocumentProvider(documentProviderFactory.getDefaultProvider());
commit 2007e9a5bb4f5667c12a32a93f5d6bfc980ac7b4
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue Jan 27 12:44:42 2015 +0000

    Android: download documents from ownCloud.
    
    Documents are downloaded to the private cache directory of the app,
    and opened from there. That directory is cleared and created again
    every time the application starts up.
    
    Change-Id: I5c05c8ae750b6ced3b419c67d84063e8ee3d84aa

diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
index 8e6d6cf..a8d1a06 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
@@ -10,6 +10,7 @@ import java.util.List;
 import org.libreoffice.storage.IFile;
 
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.files.DownloadRemoteFileOperation;
 import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
 import com.owncloud.android.lib.resources.files.RemoteFile;
 
@@ -97,8 +98,14 @@ public class OwnCloudFile implements IFile {
 
     @Override
     public File getDocument() {
-        // TODO Auto-generated method stub
-        return null;
+        if (isDirectory()) {
+            return null;
+        }
+        File downFolder = provider.getCacheDir();
+        DownloadRemoteFileOperation operation = new DownloadRemoteFileOperation(
+                file.getRemotePath(), downFolder.getAbsolutePath());
+        operation.execute(provider.getClient());
+        return new File(downFolder.getAbsolutePath() + file.getRemotePath());
     }
 
     @Override
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
index 7bd78e3..db2b698 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
@@ -1,5 +1,6 @@
 package org.libreoffice.storage.owncloud;
 
+import java.io.File;
 import java.net.URI;
 
 import org.libreoffice.R;
@@ -23,6 +24,7 @@ import com.owncloud.android.lib.resources.files.RemoteFile;
 public class OwnCloudProvider implements IDocumentProvider {
 
     private OwnCloudClient client;
+    private File cacheDir;
 
     // TODO: these must be configurable
     final private String serverUrl = "http://10.0.2.2/owncloud"; //emulator host machine
@@ -36,6 +38,13 @@ public class OwnCloudProvider implements IDocumentProvider {
         client.setCredentials(OwnCloudCredentialsFactory.newBasicCredentials(
                 userName, password));
 
+        // 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();
     }
 
     @Override
@@ -73,4 +82,27 @@ public class OwnCloudProvider implements IDocumentProvider {
         return client;
     }
 
+    /**
+     * Used by OwnCloudFiles to get the cache directory they should download
+     * files to.
+     *
+     * @return cache directory.
+     */
+    protected File getCacheDir() {
+        return cacheDir;
+    }
+
+    /**
+     * Deletes files and recursively deletes directories.
+     *
+     * @param file
+     *            File or directory to be deleted.
+     */
+    private void deleteRecursive(File file) {
+        if (file.isDirectory()) {
+            for (File child : file.listFiles())
+                deleteRecursive(child);
+        }
+        file.delete();
+    }
 }
commit abcd36f0378e5c738ebda3fbb0ac958b5c3e9a04
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Wed Jan 21 13:05:41 2015 +0000

    Android: initial implementation of ownCloud provider.
    
    This implementation can connect to a local server and browser its
    contents, but cannot download and open the documents yet.
    
    TODO:
    
    * Download and open documents.
    * UI to configure server, user and password.
    * Implement filtering to show only the documents of the desired type.
    * Improve error handling.
    
    Change-Id: I54a2e2e1d3e8ec8d824d75639e176ca452551f3e

diff --git a/android/experimental/LOAndroid3/AndroidManifest.xml.in b/android/experimental/LOAndroid3/AndroidManifest.xml.in
index 244c6db..cc61db5 100644
--- a/android/experimental/LOAndroid3/AndroidManifest.xml.in
+++ b/android/experimental/LOAndroid3/AndroidManifest.xml.in
@@ -9,6 +9,7 @@
     <uses-feature android:glEsVersion="0x00020000" android:required="true" />
     <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.INTERNET" />
 
     <application
         @ANDROID_DEBUGGABLE@
diff --git a/android/experimental/LOAndroid3/res/values/strings.xml b/android/experimental/LOAndroid3/res/values/strings.xml
index 5e5e80e..50cd31e 100644
--- a/android/experimental/LOAndroid3/res/values/strings.xml
+++ b/android/experimental/LOAndroid3/res/values/strings.xml
@@ -34,5 +34,6 @@
     <!-- Document provider names -->
     <string name="local_documents">Local documents</string>
     <string name="local_file_system">Local file system</string>
+    <string name="owncloud">ownCloud</string>
 
 </resources>
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java
index 9aa1973..3d462e6 100644
--- a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/DocumentProviderFactory.java
@@ -11,6 +11,7 @@ package org.libreoffice.storage;
 
 import org.libreoffice.storage.local.LocalDocumentsDirectoryProvider;
 import org.libreoffice.storage.local.LocalDocumentsProvider;
+import org.libreoffice.storage.owncloud.OwnCloudProvider;
 
 import android.content.Context;
 
@@ -30,8 +31,7 @@ public final class DocumentProviderFactory {
      */
     private static DocumentProviderFactory instance = null;
 
-    private IDocumentProvider[] providers = {
-            new LocalDocumentsDirectoryProvider(), new LocalDocumentsProvider() };
+    private IDocumentProvider[] providers;
 
     private String[] providerNames;
 
@@ -52,6 +52,12 @@ public final class DocumentProviderFactory {
             instance = new DocumentProviderFactory();
 
             // initialize document providers list
+            instance.providers = new IDocumentProvider[3];
+            instance.providers[0] = new LocalDocumentsDirectoryProvider();
+            instance.providers[1] = new LocalDocumentsProvider();
+            instance.providers[2] = new OwnCloudProvider(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
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
new file mode 100644
index 0000000..8e6d6cf
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudFile.java
@@ -0,0 +1,113 @@
+package org.libreoffice.storage.owncloud;
+
+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;
+
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
+import com.owncloud.android.lib.resources.files.RemoteFile;
+
+/**
+ * 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() {
+        return URI.create(file.getRemotePath());
+    }
+
+    @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 new RuntimeException(result.getLogMessage(),
+                        result.getException());
+            }
+            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) {
+        // TODO no filtering yet
+        return listFiles();
+    }
+
+    @Override
+    public IFile getParent() {
+        if (parentPath == null)
+            // this is the root node
+            return null;
+
+        return provider.createFromUri(URI.create(parentPath));
+    }
+
+    @Override
+    public File getDocument() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @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());
+    }
+}
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
new file mode 100644
index 0000000..7bd78e3
--- /dev/null
+++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/storage/owncloud/OwnCloudProvider.java
@@ -0,0 +1,76 @@
+package org.libreoffice.storage.owncloud;
+
+import java.net.URI;
+
+import org.libreoffice.R;
+import org.libreoffice.storage.IDocumentProvider;
+import org.libreoffice.storage.IFile;
+
+import android.content.Context;
+import android.net.Uri;
+
+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.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 {
+
+    private OwnCloudClient client;
+
+    // TODO: these must be configurable
+    final private String serverUrl = "http://10.0.2.2/owncloud"; //emulator host machine
+    final private String userName = "admin";
+    final private String password = "admin";
+
+    public OwnCloudProvider(Context context) {
+        Uri serverUri = Uri.parse(serverUrl);
+        client = OwnCloudClientFactory.createOwnCloudClient(serverUri,
+                context, true);
+        client.setCredentials(OwnCloudCredentialsFactory.newBasicCredentials(
+                userName, password));
+
+    }
+
+    @Override
+    public IFile getRootDirectory() {
+        return createFromUri(URI.create(FileUtils.PATH_SEPARATOR));
+    }
+
+    @Override
+    public IFile createFromUri(URI uri) {
+        ReadRemoteFileOperation refreshOperation = new ReadRemoteFileOperation(
+                uri.getPath());
+        RemoteOperationResult result = refreshOperation.execute(client);
+        if (!result.isSuccess()) {
+            throw new RuntimeException(result.getLogMessage(),
+                    result.getException());
+        }
+        if (result.getData().size() > 0) {
+            return new OwnCloudFile(this, (RemoteFile) result.getData().get(0));
+        }
+        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;
+    }
+
+}
commit 4e27edb6540c6f6b31427ae60b457e0416450850
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Mon Feb 2 19:49:37 2015 +0000

    Android: add ownCloud library to the build.
    
    Library code from https://github.com/owncloud/android-library
    
    This patch downloads, builds and installs the library from a tarball
    uploaded to http://dev-www.libreoffice.org/src/.
    
    WARNING: this patch should *not* be merged to master. The tarball
    contains some binary .jar files and that is not acceptable.
    
    Change-Id: I28afaea4dabe2dab869b53b1881f4d5a6522943f

diff --git a/Makefile.fetch b/Makefile.fetch
index 7aee66a..390d3d0 100644
--- a/Makefile.fetch
+++ b/Makefile.fetch
@@ -189,6 +189,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_host.mk $(SRCDIR)/download.lst $(SRCDIR)
 		$(call fetch_Optional,OPENLDAP,OPENLDAP_TARBALL) \
 		$(call fetch_Optional,OPENSSL,OPENSSL_TARBALL) \
 		$(call fetch_Optional,ORCUS,ORCUS_TARBALL) \
+		$(call fetch_Optional,OWNCLOUD_ANDROID_LIB,OWNCLOUD_ANDROID_LIB_TARBALL) \
 		$(call fetch_Optional,PAGEMAKER,PAGEMAKER_TARBALL) \
 		$(call fetch_Optional,POPPLER,POPPLER_TARBALL) \
 		$(call fetch_Optional,POSTGRESQL,POSTGRESQL_TARBALL) \
diff --git a/RepositoryExternal.mk b/RepositoryExternal.mk
index 9789959..cba2e63 100644
--- a/RepositoryExternal.mk
+++ b/RepositoryExternal.mk
@@ -4018,4 +4018,20 @@ endef
 
 endif
 
+ifeq (OWNCLOUD_ANDROID_LIB,$(filter OWNCLOUD_ANDROID_LIB,$(BUILD_TYPE)))
+
+$(eval $(call gb_Helper_register_jars,OXT,\
+	owncloud-android-library \
+))
+
+define gb_Jar__use_owncloud_android_lib
+$(call gb_Jar_use_external_project,$(1),owncloud-android-lib)
+$(call gb_Jar_use_external_jar,$(1),$(call gb_UnpackedTarball_get_dir,owncloud-android-lib)/bin/owncloud-android-library.jar)
+endef
+define gb_ExternalProject__use_owncloud_android_lib
+$(call gb_ExternalProject_use_external_project,$(1),owncloud_android_lib)
+endef
+
+endif
+
 # vim: set noet sw=4 ts=4:
diff --git a/android/experimental/LOAndroid3/Makefile b/android/experimental/LOAndroid3/Makefile
index c5c18c7..20674bb 100644
--- a/android/experimental/LOAndroid3/Makefile
+++ b/android/experimental/LOAndroid3/Makefile
@@ -33,6 +33,13 @@ build-ant: android_version_setup copy-stuff link-so properties
 	for F in unoil; do \
 	    $(call COPYJAR,$(INSTDIR)/$(LIBO_SHARE_JAVA_FOLDER)/$${F}.jar); \
 	done
+	#ownCloud lib dependencies
+	$(call COPYJAR,$(WORKDIR)/UnpackedTarball/owncloud_android_lib/bin/owncloud-android-library.jar)
+	for F in commons-httpclient-3.1 \
+		 jackrabbit-webdav-2.7.2 \
+		 slf4j-api-1.7.5; do \
+	    $(call COPYJAR,$(WORKDIR)/UnpackedTarball/owncloud_android_lib/libs/$${F}.jar); \
+	done
 #
 	unset JAVA_HOME && $(ANT) $(if $(VERBOSE)$(verbose),,-quiet) $(if $(ENABLE_RELEASE_BUILD),release,debug)
 
diff --git a/configure.ac b/configure.ac
index d4594e8..5416d70 100644
--- a/configure.ac
+++ b/configure.ac
@@ -498,6 +498,9 @@ if test -n "$with_android_ndk"; then
             ;;
         esac
     fi
+
+    # remember to download the ownCloud Android library later
+    BUILD_TYPE="$BUILD_TYPE OWNCLOUD_ANDROID_LIB"
 fi
 AC_SUBST(ANDROID_NDK_GDBSERVER)
 AC_SUBST(ANDROID_APP_ABI)
diff --git a/download.lst b/download.lst
index ef1af63..b94203c 100644
--- a/download.lst
+++ b/download.lst
@@ -118,6 +118,8 @@ export OPENLDAP_TARBALL := 804c6cb5698db30b75ad0ff1c25baefd-openldap-2.4.31.tgz
 export OPENSSL_MD5SUM := f7175c9cd3c39bb1907ac8bba9df8ed3
 export OPENSSL_TARBALL := openssl-1.0.1j.tar.gz
 export ORCUS_TARBALL := 7681383be6ce489d84c1c74f4e7f9643-liborcus-0.7.0.tar.bz2
+export OWNCLOUD_ANDROID_LIB_MD5SUM := 2ee09f67d3ea1a137c8d3e6ed60fed22
+export OWNCLOUD_ANDROID_LIB_TARBALL := owncloud-android-library-0.9.4.tar.gz
 export PAGEMAKER_MD5SUM := 795cc7a59ace4db2b12586971d668671
 export PAGEMAKER_TARBALL := libpagemaker-0.0.2.tar.bz2
 export PIXMAN_TARBALL := c63f411b3ad147db2bcce1bf262a0e02-pixman-0.24.4.tar.bz2
diff --git a/external/Module_external.mk b/external/Module_external.mk
index 6d38fd5..8b4fb6c 100644
--- a/external/Module_external.mk
+++ b/external/Module_external.mk
@@ -80,6 +80,7 @@ $(eval $(call gb_Module_add_moduledirs,external,\
 	$(call gb_Helper_optional,OPENLDAP,openldap) \
 	$(call gb_Helper_optional,OPENSSL,openssl) \
 	$(call gb_Helper_optional,ORCUS,liborcus) \
+	$(call gb_Helper_optional,OWNCLOUD_ANDROID_LIB,owncloud-android-lib) \
 	$(call gb_Helper_optional,PAGEMAKER,libpagemaker) \
 	$(call gb_Helper_optional,POPPLER,poppler) \
 	$(call gb_Helper_optional,POSTGRESQL,postgresql) \
diff --git a/external/owncloud-android-lib/ExternalProject_owncloud_android_lib.mk b/external/owncloud-android-lib/ExternalProject_owncloud_android_lib.mk
new file mode 100644
index 0000000..21081c4
--- /dev/null
+++ b/external/owncloud-android-lib/ExternalProject_owncloud_android_lib.mk
@@ -0,0 +1,24 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_ExternalProject_ExternalProject,owncloud_android_lib))
+
+$(eval $(call gb_ExternalProject_register_targets,owncloud_android_lib,\
+	build \
+))
+
+$(call gb_ExternalProject_get_state_target,owncloud_android_lib,build) :
+	$(call gb_ExternalProject_run,build,\
+	$(ICECREAM_RUN) "$(ANT)" \
+		-q \
+		-f build.xml \
+		release \
+	)
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/owncloud-android-lib/Makefile b/external/owncloud-android-lib/Makefile
new file mode 100644
index 0000000..e4968cf
--- /dev/null
+++ b/external/owncloud-android-lib/Makefile
@@ -0,0 +1,7 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/owncloud-android-lib/Module_owncloud-android-lib.mk b/external/owncloud-android-lib/Module_owncloud-android-lib.mk
new file mode 100644
index 0000000..486ed40
--- /dev/null
+++ b/external/owncloud-android-lib/Module_owncloud-android-lib.mk
@@ -0,0 +1,17 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_Module_Module,owncloud_android_lib))
+
+$(eval $(call gb_Module_add_targets,owncloud_android_lib, \
+	ExternalProject_owncloud_android_lib \
+	UnpackedTarball_owncloud_android_lib \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/external/owncloud-android-lib/README b/external/owncloud-android-lib/README
new file mode 100644
index 0000000..6435c9b
--- /dev/null
+++ b/external/owncloud-android-lib/README
@@ -0,0 +1,4 @@
+Library required to access ownCloud servers from Android.
+
+Code from https://github.com/owncloud/android-library, our tarball is the 0.9.4
+release sans the test and example projects.
diff --git a/external/owncloud-android-lib/UnpackedTarball_owncloud_android_lib.mk b/external/owncloud-android-lib/UnpackedTarball_owncloud_android_lib.mk
new file mode 100644
index 0000000..0866f6f
--- /dev/null
+++ b/external/owncloud-android-lib/UnpackedTarball_owncloud_android_lib.mk
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_UnpackedTarball_UnpackedTarball,owncloud_android_lib))
+
+$(eval $(call gb_UnpackedTarball_set_tarball,owncloud_android_lib,$(OWNCLOUD_ANDROID_LIB_TARBALL)))
+
+# vim: set noet sw=4 ts=4:
commit b0fdf6cf11ee46d46925e9cd9fa2768a1b49bb64
Author: Supreme Aryal <supremearyal at gmail.com>
Date:   Tue Dec 9 00:09:39 2014 -0500

    Compute n-th root of negative numbers where n is odd. (tdf#69293)
    
    Compute expressions like (-8)^(1/3) correctly. This makes
    calculations compatible with Excel. Exponents must reduce
    to the form 1/n.
    
    Change-Id: I007c818f584323f80f2f6b1000d931f19a4590ad

diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index b6d616e..e6ca138 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1654,7 +1654,20 @@ void ScInterpreter::ScPow()
             PushIllegalArgument();
     }
     else
-        PushDouble(pow(fVal1,fVal2));
+    {
+        if (fVal1 < 0 && fVal2 != 0.0)
+        {
+            int i = (int) (1 / fVal2 + ((fVal2 < 0) ? -0.5 : 0.5));
+            if (rtl::math::approxEqual(1 / ((double) i), fVal2) && i % 2 != 0)
+                PushDouble(-pow(-fVal1, fVal2));
+            else
+                PushDouble(pow(fVal1, fVal2));
+        }
+        else
+        {
+            PushDouble(pow(fVal1,fVal2));
+        }
+    }
 }
 
 namespace {
commit e24ca726875a4533352d3bf06bae3d9c07e79a8d
Author: Jan Holesovsky <kendy at collabora.com>
Date:   Fri Feb 13 11:37:48 2015 +0100

    native-code.py: Don't add the entire libchartcorelo.a.
    
    Instead, just add the constructors of the needed services.  Tested with
    various-charts.ods from tdf#89364.
    
    Change-Id: I98df03bfc19aeacaa92e4693e7934c8503f183e1

diff --git a/solenv/bin/native-code.py b/solenv/bin/native-code.py
index 62a668e..653a524 100755
--- a/solenv/bin/native-code.py
+++ b/solenv/bin/native-code.py
@@ -24,7 +24,6 @@ core_factory_list = [
     ("libembobj.a", "embobj_component_getFactory"),
     ("libreflectionlo.a", "reflection_component_getFactory"),
     ("libstocserviceslo.a", "stocservices_component_getFactory"),
-    ("libchartcorelo.a", "chartcore_component_getFactory"),
     ("libcomphelper.a", "comphelp_component_getFactory"),
     ("libconfigmgrlo.a", "configmgr_component_getFactory"),
     ("libdrawinglayerlo.a", "drawinglayer_component_getFactory"),
@@ -62,6 +61,27 @@ core_factory_list = [
     ]
 
 core_constructor_list = [
+# chart2/source/chartcore.component
+    "com_sun_star_comp_chart_AreaChartType_get_implementation",
+    "com_sun_star_comp_chart_BarChartType_get_implementation",
+    "com_sun_star_comp_chart_BubbleChartType_get_implementation",
+    "com_sun_star_comp_chart_CandleStickChartType_get_implementation",
+    "com_sun_star_comp_chart_ChartTypeManager_get_implementation",
+    "com_sun_star_comp_chart_ColumnChartType_get_implementation",
+    "com_sun_star_comp_chart_DataSeries_get_implementation",
+    "com_sun_star_comp_chart_FilledNetChartType_get_implementation",
+    "com_sun_star_comp_chart_GL3DBarChartType_get_implementation",
+    "com_sun_star_comp_chart_FormattedString_get_implementation",
+    "com_sun_star_comp_chart_LineChartType_get_implementation",
+    "com_sun_star_comp_chart_NetChartType_get_implementation",
+    "com_sun_star_comp_chart_PieChartType_get_implementation",
+    "com_sun_star_comp_chart_ScatterChartType_get_implementation",
+    "com_sun_star_comp_chart2_Axis_get_implementation",
+    "com_sun_star_comp_chart2_ChartModel_get_implementation",
+    "com_sun_star_comp_chart2_Diagram_get_implementation",
+    "com_sun_star_comp_chart2_LabeledDataSequence_get_implementation",
+    "com_sun_star_comp_chart2_Legend_get_implementation",
+    "com_sun_star_comp_chart2_XMLFilter_get_implementation",
 # chart2/source/controller/chartcontroller.component
     "com_sun_star_comp_chart2_ChartDocumentWrapper_get_implementation",
 # framework/util/fwk.component
commit 21796a5fb92fd9773017b782a654a8b5a190cc66
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Fri Feb 13 10:33:37 2015 +0000

    Resolves: tdf#79569 crash undoing tricky cell merge
    
    Change-Id: I68d774d0d3758cdb67864d7939a7e1167dd9a7df

diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index 9f1e754..9778de2 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -1351,21 +1351,22 @@ void _SaveBox::CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl
     {
         // search box for StartNode in old table
         SwTableBox* pBox = rTbl.GetTblBox( nSttNode );
-        OSL_ENSURE( pBox, "Where is my TableBox?" );
-
-        SwFrmFmt* pOld = pBox->GetFrmFmt();
-        pBox->RegisterToFormat( *pFmt );
-        if( !pOld->GetDepends() )
-            delete pOld;
+        if (pBox)
+        {
+            SwFrmFmt* pOld = pBox->GetFrmFmt();
+            pBox->RegisterToFormat( *pFmt );
+            if( !pOld->GetDepends() )
+                delete pOld;
 
-        pBox->setRowSpan( nRowSpan );
+            pBox->setRowSpan( nRowSpan );
 
-        SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
-        pTBoxes->erase( std::find( pTBoxes->begin(), pTBoxes->end(), pBox ) );
+            SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+            pTBoxes->erase( std::find( pTBoxes->begin(), pTBoxes->end(), pBox ) );
 
-        pBox->SetUpper( &rParent );
-        pTBoxes = &rParent.GetTabBoxes();
-        pTBoxes->push_back( pBox );
+            pBox->SetUpper( &rParent );
+            pTBoxes = &rParent.GetTabBoxes();
+            pTBoxes->push_back( pBox );
+        }
     }
 
     if( pNext )
commit 9df101c7e9ff36a1425f96ec78aaf11f23577842
Author: Stanislav Horacek <stanislav.horacek at gmail.com>
Date:   Thu Feb 12 19:58:13 2015 +0100

    Updated core
    Project: help  377e8876396a87ae09b82ce17b67d8bef5b26abe
    
    tdf#89294 scanner items are now in Media submenu
    
    Change-Id: Ib71d92143e39e6fbc280a115a548c2d827764fff
    Reviewed-on: https://gerrit.libreoffice.org/14447
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/helpcontent2 b/helpcontent2
index 0c8a78a..377e887 160000
--- a/helpcontent2
+++ b/helpcontent2
@@ -1 +1 @@
-Subproject commit 0c8a78a426e48b9adf19ff75c5d8c7cb112e91dd
+Subproject commit 377e8876396a87ae09b82ce17b67d8bef5b26abe
commit 8893a361238ce8e151f1db65a36a8c2506d26594
Author: Albert Thuswaldner <albert.thuswaldner at gmail.com>
Date:   Thu Feb 12 21:20:00 2015 +0100

    Translated german commments in sc/source/core/data/table1-3.cxx
    
    Change-Id: Ic28cb4f9371caf39e783f39fd8a117260b962bfe
    Reviewed-on: https://gerrit.libreoffice.org/14451
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 1aa5430..7ace7b5 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -86,15 +86,15 @@ void GetOptimalHeightsInColumn(
 {
     SCSIZE nCount = static_cast<SCSIZE>(nEndRow-nStartRow+1);
 
-    //  zuerst einmal ueber den ganzen Bereich
-    //  (mit der letzten Spalte in der Hoffnung, dass die am ehesten noch auf
-    //   Standard formatiert ist)
+    //  first, one time over the whole range
+    //  (with the last column in the hope that they most likely still are
+    //  on standard format)
 
     std::vector<sal_uInt16>& rHeights = rCxt.getHeightArray();
 
     pCol[MAXCOL].GetOptimalHeight(rCxt, nStartRow, nEndRow, 0, 0);
 
-    //  daraus Standardhoehe suchen, die im unteren Bereich gilt
+    //  from there search for the standard height that is in use in the lower part
 
     sal_uInt16 nMinHeight = rHeights[nCount-1];
     SCSIZE nPos = nCount-1;
@@ -103,14 +103,14 @@ void GetOptimalHeightsInColumn(
     SCROW nMinStart = nStartRow + nPos;
 
     sal_uLong nWeightedCount = 0;
-    for (SCCOL nCol=0; nCol<MAXCOL; nCol++)     // MAXCOL schon oben
+    for (SCCOL nCol=0; nCol<MAXCOL; nCol++)     // MAXCOL already above
     {
         pCol[nCol].GetOptimalHeight(rCxt, nStartRow, nEndRow, nMinHeight, nMinStart);
 
         if (pProgress)
         {
             sal_uLong nWeight = pCol[nCol].GetWeightedCount();
-            if (nWeight)        // nochmal denselben Status muss auch nicht sein
+            if (nWeight)        // does not have to be the same Status
             {
                 nWeightedCount += nWeight;
                 pProgress->SetState( nWeightedCount + nProgressStart );
@@ -326,9 +326,9 @@ ScTable::~ScTable()
         {
             aCol[nCol].FreeNotes();
         }
-        //  nicht im dtor die Pages in der falschen Reihenfolge loeschen
-        //  (nTab stimmt dann als Page-Number nicht!)
-        //  In ScDocument::Clear wird hinterher per Clear am Draw Layer alles geloescht.
+        //  In the dtor, don't delete the pages in the wrong order.
+        //  (or else nTab does not reflect the page number!)
+        //  In ScDocument::Clear is afterwards used from Clear at the Draw Layer to delete everything.
 
         ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer();
         if (pDrawLayer)
@@ -422,10 +422,10 @@ void ScTable::SetLink( sal_uInt8 nMode,
                         const OUString& rTab, sal_uLong nRefreshDelay )
 {
     nLinkMode = nMode;
-    aLinkDoc = rDoc;        // Datei
+    aLinkDoc = rDoc;        // File
     aLinkFlt = rFlt;        // Filter
-    aLinkOpt = rOpt;        // Filter-Optionen
-    aLinkTab = rTab;        // Tabellenname in Quelldatei
+    aLinkOpt = rOpt;        // Filter options
+    aLinkTab = rTab;        // Sheet name in source file
     nLinkRefreshDelay = nRefreshDelay;  // refresh delay in seconds, 0==off
 
     if (IsStreamValid())
@@ -449,7 +449,7 @@ long ScTable::GetNeededSize( SCCOL nCol, SCROW nRow,
                                 bool bWidth, bool bTotalSize )
 {
     ScNeededSizeOptions aOptions;
-    aOptions.bSkipMerged = false;       // zusammengefasste mitzaehlen
+    aOptions.bSkipMerged = false;       // count merged cells
     aOptions.bTotalSize  = bTotalSize;
 
     return aCol[nCol].GetNeededSize
@@ -568,7 +568,7 @@ bool ScTable::GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, bool bNotes, bool bF
     SCROW nMaxY = 0;
     SCCOL i;
 
-    for (i=0; i<=MAXCOL; i++)               // Daten testen
+    for (i=0; i<=MAXCOL; i++)               // Test data
         {
             if (!aCol[i].IsEmptyData())
             {
@@ -600,7 +600,7 @@ bool ScTable::GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, bool bNotes, bool bF
 
     SCCOL nMaxDataX = nMaxX;
 
-    for (i=0; i<=MAXCOL; i++)               // Attribute testen
+    for (i=0; i<=MAXCOL; i++)               // Test attribute
     {
         SCROW nLastRow;
         if (aCol[i].GetLastVisibleAttr( nLastRow, bFullFormattedArea ))
@@ -612,7 +612,7 @@ bool ScTable::GetPrintArea( SCCOL& rEndCol, SCROW& rEndRow, bool bNotes, bool bF
         }
     }
 
-    if (nMaxX == MAXCOL)                    // Attribute rechts weglassen
+    if (nMaxX == MAXCOL)                    // omit attribute at the right
     {
         --nMaxX;
         while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1]) )
@@ -658,7 +658,7 @@ bool ScTable::GetPrintAreaHor( SCROW nStartRow, SCROW nEndRow,
     SCCOL nMaxX = 0;
     SCCOL i;
 
-    for (i=0; i<=MAXCOL; i++)               // Attribute testen
+    for (i=0; i<=MAXCOL; i++)               // Test attribute
     {
         if (aCol[i].HasVisibleAttrIn( nStartRow, nEndRow ))
         {
@@ -667,7 +667,7 @@ bool ScTable::GetPrintAreaHor( SCROW nStartRow, SCROW nEndRow,
         }
     }
 
-    if (nMaxX == MAXCOL)                    // Attribute rechts weglassen
+    if (nMaxX == MAXCOL)                    // omit attribute at the right
     {
         --nMaxX;
         while ( nMaxX>0 && aCol[nMaxX].IsVisibleAttrEqual(aCol[nMaxX+1], nStartRow, nEndRow) )
@@ -695,7 +695,7 @@ bool ScTable::GetPrintAreaVer( SCCOL nStartCol, SCCOL nEndCol,
     SCROW nMaxY = 0;
     SCCOL i;
 
-    for (i=nStartCol; i<=nEndCol; i++)              // Attribute testen
+    for (i=nStartCol; i<=nEndCol; i++)              // Test attribute
     {
         SCROW nLastRow;
         if (aCol[i].GetLastVisibleAttr( nLastRow ))
@@ -706,7 +706,7 @@ bool ScTable::GetPrintAreaVer( SCCOL nStartCol, SCCOL nEndCol,
         }
     }
 
-    for (i=nStartCol; i<=nEndCol; i++)              // Daten testen
+    for (i=nStartCol; i<=nEndCol; i++)              // Test data
     {
         if (!aCol[i].IsEmptyData())
         {
@@ -740,7 +740,7 @@ bool ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
     SCROW nMinY = MAXROW;
     SCCOL i;
 
-    for (i=0; i<=MAXCOL; i++)                   // Attribute testen
+    for (i=0; i<=MAXCOL; i++)                   // Test attribute
     {
         SCROW nFirstRow;
         if (aCol[i].GetFirstVisibleAttr( nFirstRow ))
@@ -753,9 +753,9 @@ bool ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
         }
     }
 
-    if (nMinX == 0)                                     // Attribute links weglassen
+    if (nMinX == 0)                                     // omit attribute at the right
     {
-        if ( aCol[0].IsVisibleAttrEqual(aCol[1]) )      // keine einzelnen
+        if ( aCol[0].IsVisibleAttrEqual(aCol[1]) )      // no single ones
         {
             ++nMinX;
             while ( nMinX<MAXCOL && aCol[nMinX].IsVisibleAttrEqual(aCol[nMinX-1]) )
@@ -764,7 +764,7 @@ bool ScTable::GetDataStart( SCCOL& rStartCol, SCROW& rStartRow ) const
     }
 
     bool bDatFound = false;
-    for (i=0; i<=MAXCOL; i++)                   // Daten testen
+    for (i=0; i<=MAXCOL; i++)                   // Test data
     {
         if (!aCol[i].IsEmptyData())
         {
@@ -1222,7 +1222,7 @@ bool ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark,
 void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
                                 bool bMarked, bool bUnprotected, const ScMarkData& rMark ) const
 {
-    if (bUnprotected && !IsProtected())     // Tabelle ueberhaupt geschuetzt?
+    if (bUnprotected && !IsProtected())     // Is sheet really protected?
         bUnprotected = false;
 
     sal_uInt16 nWrap = 0;
@@ -1233,7 +1233,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
     nRow = sal::static_int_cast<SCsROW>( nRow + nMovY );
 
     OSL_ENSURE( !nMovY || !bUnprotected,
-                "GetNextPos mit bUnprotected horizontal nicht implementiert" );
+                "GetNextPos with bUnprotected horizontal not implemented" );
 
     if ( nMovY && bMarked )
     {
@@ -1242,7 +1242,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
         while ( ValidRow(nRow) &&
                 (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
         {
-            //  ausgeblendete ueberspringen (s.o.)
+            //  skip hidden rows (see above)
             nRow += nMovY;
             nRow = rMark.GetNextMarked( nCol, nRow, bUp );
         }
@@ -1272,7 +1272,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
             while ( ValidRow(nRow) &&
                     (RowHidden(nRow) || pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) )
             {
-                //  ausgeblendete ueberspringen (s.o.)
+                //  skip hidden rows (see above)
                 nRow += nMovY;
                 nRow = rMark.GetNextMarked( nCol, nRow, bUp );
             }
@@ -1281,7 +1281,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
 
     if ( nMovX && ( bMarked || bUnprotected ) )
     {
-        // initiales Weiterzaehlen wrappen:
+        // wrap initial skip counting:
         if (nCol<0)
         {
             nCol = MAXCOL;
@@ -1302,7 +1302,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
             boost::scoped_array<SCsROW> pNextRows(new SCsROW[MAXCOL+1]);
             SCCOL i;
 
-            if ( nMovX > 0 )                            //  vorwaerts
+            if ( nMovX > 0 )                            //  forward
             {
                 for (i=0; i<=MAXCOL; i++)
                     pNextRows[i] = (i<nCol) ? (nRow+1) : nRow;
@@ -1317,7 +1317,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
 
                     SCsROW nMinRow = MAXROW+1;
                     for (i=0; i<=MAXCOL; i++)
-                        if (pNextRows[i] < nMinRow)     // bei gleichen den linken
+                        if (pNextRows[i] < nMinRow)     // when two equal on the left
                         {
                             nMinRow = pNextRows[i];
                             nCol = i;
@@ -1326,16 +1326,16 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
 
                     if ( nRow > MAXROW )
                     {
-                        if (++nWrap >= 2) break;        // ungueltigen Wert behalten
+                        if (++nWrap >= 2) break;        // handle invalid value
                         nCol = 0;
                         nRow = 0;
                         for (i=0; i<=MAXCOL; i++)
-                            pNextRows[i] = 0;           // alles ganz von vorne
+                            pNextRows[i] = 0;           // do it all over again
                     }
                 }
                 while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
             }
-            else                                        //  rueckwaerts
+            else                                        //  backwards
             {
                 for (i=0; i<=MAXCOL; i++)
                     pNextRows[i] = (i>nCol) ? (nRow-1) : nRow;
@@ -1350,7 +1350,7 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
 
                     SCsROW nMaxRow = -1;
                     for (i=0; i<=MAXCOL; i++)
-                        if (pNextRows[i] >= nMaxRow)    // bei gleichen den rechten
+                        if (pNextRows[i] >= nMaxRow)    // when two equal on the right
                         {
                             nMaxRow = pNextRows[i];
                             nCol = i;
@@ -1359,11 +1359,11 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
 
                     if ( nRow < 0 )
                     {
-                        if (++nWrap >= 2) break;        // ungueltigen Wert behalten
+                        if (++nWrap >= 2) break;        // handle invalid value
                         nCol = MAXCOL;
                         nRow = MAXROW;
                         for (i=0; i<=MAXCOL; i++)
-                            pNextRows[i] = MAXROW;      // alles ganz von vorne
+                            pNextRows[i] = MAXROW;      // do it all over again
                     }
                 }
                 while ( !ValidNextPos(nCol, nRow, rMark, bMarked, bUnprotected) );
@@ -1371,9 +1371,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY,
         }
     }
 
-    //  ungueltige Werte kommen z.b. bei Tab heraus,
-    //  wenn nicht markiert und nicht geschuetzt ist (linker / rechter Rand),
-    //  dann Werte unveraendert lassen
+    //  Invalid values show up for instane for Tab, when nothing is selected and not
+    //  protected (left / right edge), then leave values unchanged.
 
     if (ValidColRow(nCol,nRow))
     {
@@ -1389,7 +1388,7 @@ bool ScTable::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMa
     if ( !pMarkArray )
         return false;
 
-    ++rRow;                 // naechste Zelle ist gesucht
+    ++rRow;                 // next row
 
     while ( rCol <= MAXCOL )
     {
@@ -1425,16 +1424,16 @@ bool ScTable::GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMa
                     return true;
                 }
 
-                rRow = nEnd + 1;                // naechsten markierten Bereich suchen
+                rRow = nEnd + 1;                // Search for next selected range
             }
             else
-                rRow = MAXROW + 1;              // Ende der Spalte
+                rRow = MAXROW + 1;              // End of column
         }
         rRow = 0;
-        ++rCol;                                 // naechste Spalte testen
+        ++rCol;                                 // test next column
     }
 
-    return false;                               // alle Spalten durch
+    return false;                               // Through all columns
 }
 
 void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
@@ -1537,7 +1536,7 @@ void ScTable::UpdateReference(
             {
                 *pRepeatColRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
                 bRecalcPages = true;
-                nRepeatStartX = nSCol;  // fuer UpdatePageBreaks
+                nRepeatStartX = nSCol;  // for UpdatePageBreaks
                 nRepeatEndX = nECol;
             }
         }
@@ -1557,7 +1556,7 @@ void ScTable::UpdateReference(
             {
                 *pRepeatRowRange = ScRange( nSCol, nSRow, 0, nECol, nERow, 0 );
                 bRecalcPages = true;
-                nRepeatStartY = nSRow;  // fuer UpdatePageBreaks
+                nRepeatStartY = nSRow;  // for UpdatePageBreaks
                 nRepeatEndY = nERow;
             }
         }
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 6b4663c..c12bebb 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -110,7 +110,7 @@ bool ScTable::SetOutlineTable( const ScOutlineTable* pNewOutline )
     else
         pOutlineTable = NULL;
 
-    return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY );        // Groesse geaendert ?
+    return ( nNewSizeX != nOldSizeX || nNewSizeY != nOldSizeY );        // changed size?
 }
 
 void ScTable::StartOutlineTable()
@@ -466,7 +466,7 @@ void ScTable::DeleteSelection( InsertDeleteFlags nDelFlag, const ScMarkData& rMa
             mpCondFormatList->DeleteArea( pRange->aStart.Col(), pRange->aStart.Row(), pRange->aEnd.Col(), pRange->aEnd.Row() );
     }
 
-        // Zellschutz auf geschuetzter Tabelle nicht setzen
+        // Do not set protected cell in a protected sheet
 
     if ( IsProtected() && (nDelFlag & IDF_ATTRIB) )
     {
@@ -522,7 +522,7 @@ void ScTable::CopyToClip(
     pTable->CopyRowHidden(*this, 0, nRow2);
     pTable->CopyRowFiltered(*this, 0, nRow2);
 
-    //  ggf. Formeln durch Werte ersetzen
+    // If necessary replace formulas with values
 
     if ( IsProtected() )
         for (i = nCol1; i <= nCol2; i++)
@@ -683,7 +683,7 @@ void ScTable::CopyFromClip(
                 }
             }
 
-            // Zellschutz auf geschuetzter Tabelle nicht setzen
+            // Do not set protected cell in a protected sheet
             if (IsProtected() && (rCxt.getInsertFlag() & IDF_ATTRIB))
             {
                 ScPatternAttr aPattern(pDocument->GetPool());
@@ -705,7 +705,7 @@ void ScTable::MixData(
         aCol[i].MixData(rCxt, nRow1, nRow2, nFunction, bSkipEmpty, pSrcTab->aCol[i]);
 }
 
-//  Markierung von diesem Dokument
+// Selection form this document
 void ScTable::MixMarked(
     sc::MixDocContext& rCxt, const ScMarkData& rMark, sal_uInt16 nFunction,
     bool bSkipEmpty, const ScTable* pSrcTab )
@@ -802,8 +802,8 @@ public:
         ScFormulaCell* pNew = new ScFormulaCell(
             *p, mrClipTab.GetDoc(), getDestPos(nRow), SC_CLONECELL_STARTLISTENING);
 
-        //  Referenzen drehen
-        //  bei Cut werden Referenzen spaeter per UpdateTranspose angepasst
+        //  rotate reference
+        //  for Cut, the referneces are later adjusted through UpdateTranspose
 
         if (!mbWasCut)
             pNew->TransposeReference();
@@ -1091,7 +1091,7 @@ void ScTable::CopyToTable(
             aCol[i].CopyToColumn(rCxt, nRow1, nRow2, nFlags, bMarked,
                                 pDestTab->aCol[i], pMarkData, bAsLink);
 
-    if (!bColRowFlags)      // Spaltenbreiten/Zeilenhoehen/Flags
+    if (!bColRowFlags)      // Column widths/Row heights/Flags
         return;
 
     if(pDestTab->pDocument->IsUndo() && (nFlags & IDF_ATTRIB))
@@ -1109,7 +1109,7 @@ void ScTable::CopyToTable(
         pNewDBData->MoveTo(pDestTab->nTab, aCol1, aRow1, aCol2, aRow2);
         pDestTab->SetAnonymousDBData(pNewDBData);
     }
-    //  Charts muessen beim Ein-/Ausblenden angepasst werden
+    //  Charts have to be adjusted when hide/show
     ScChartListenerCollection* pCharts = pDestTab->pDocument->GetChartListenerCollection();
 
     bool bFlagChange = false;
@@ -1271,7 +1271,7 @@ void ScTable::MarkScenarioIn( ScMarkData& rDestMark, sal_uInt16 nNeededBits ) co
 {
     OSL_ENSURE( bScenario, "bScenario == FALSE" );
 
-    if ( ( nScenarioFlags & nNeededBits ) != nNeededBits )  // alle Bits gesetzt?
+    if ( ( nScenarioFlags & nNeededBits ) != nNeededBits )  // Are all Bits set?
         return;
 
     for (SCCOL i=0; i<=MAXCOL; i++)
@@ -1315,7 +1315,7 @@ const ScRangeList* ScTable::GetScenarioRanges() const
     {
         ((ScTable*)this)->pScenarioRanges = new ScRangeList;
         ScMarkData aMark;
-        MarkScenarioIn( aMark, 0 );     // immer
+        MarkScenarioIn( aMark, 0 );     // always
         aMark.FillRangeListWithMarks( pScenarioRanges, false );
     }
     return pScenarioRanges;
@@ -1688,7 +1688,7 @@ void ScTable::SetAllFormulasDirty( const sc::SetFormulaDirtyContext& rCxt )
 void ScTable::SetDirty( const ScRange& rRange, ScColumn::BroadcastMode eMode )
 {
     bool bOldAutoCalc = pDocument->GetAutoCalc();
-    pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
+    pDocument->SetAutoCalc( false );    // avoid multiple recalculations
     SCCOL nCol2 = rRange.aEnd.Col();
     for (SCCOL i=rRange.aStart.Col(); i<=nCol2; i++)
         aCol[i].SetDirty(rRange.aStart.Row(), rRange.aEnd.Row(), eMode);
@@ -1708,7 +1708,7 @@ void ScTable::SetTableOpDirty( const ScRange& rRange )
 void ScTable::SetDirtyAfterLoad()
 {
     bool bOldAutoCalc = pDocument->GetAutoCalc();
-    pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
+    pDocument->SetAutoCalc( false );    // avoid multiple recalculations
     for (SCCOL i=0; i<=MAXCOL; i++)
         aCol[i].SetDirtyAfterLoad();
     pDocument->SetAutoCalc( bOldAutoCalc );
@@ -1717,7 +1717,7 @@ void ScTable::SetDirtyAfterLoad()
 void ScTable::SetDirtyIfPostponed()
 {
     bool bOldAutoCalc = pDocument->GetAutoCalc();
-    pDocument->SetAutoCalc( false );    // Mehrfachberechnungen vermeiden
+    pDocument->SetAutoCalc( false );    // avoid multiple recalculations
     for (SCCOL i=0; i<=MAXCOL; i++)
         aCol[i].SetDirtyIfPostponed();
     pDocument->SetAutoCalc( bOldAutoCalc );
@@ -1937,7 +1937,7 @@ SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCO
                             SCCOL nCol, SCROW nAttrRow1, SCROW nAttrRow2, SCSIZE nArrY,
                             const ScPatternAttr* pPattern, const SfxItemSet* pCondSet )
 {
-    //  Rueckgabe = neues nArrY
+    //  Return value = new nArrY
 
     sal_uInt8 nRotDir = pPattern->GetRotateDir( pCondSet );
     if ( nRotDir != SC_ROTDIR_NONE )
@@ -1973,7 +1973,7 @@ SCSIZE ScTable::FillMaxRot( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCO
                     bool bHitOne = true;
                     if ( nCol > nX2+1 )
                     {
-                        // reicht die gedrehte Zelle bis in den sichtbaren Bereich?
+                        // Does the rotated cell extend into the visable range?
 
                         SCCOL nTouchedCol = nCol;
                         long nWidth = static_cast<long>(mpRowHeights->getValue(nRow) * nFactor);
@@ -2010,7 +2010,7 @@ void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCC
         return;
     }
 
-    //  nRotMaxCol ist auf SC_ROTMAX_NONE initialisiert, nRowNo ist schon gesetzt
+    //  nRotMaxCol is initalized to SC_ROTMAX_NONE, nRowNo is already set
 
     SCROW nY1 = pRowInfo[0].nRowNo;
     SCROW nY2 = pRowInfo[nArrCount-1].nRowNo;
@@ -2030,8 +2030,8 @@ void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCC
                 if ( pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, true, &pCondItem )
                         == SfxItemState::SET )
                 {
-                    //  alle Formate durchgehen, damit die Zellen nicht einzeln
-                    //  angeschaut werden muessen
+                    //  Run through all formats, so that each cell does not have to be
+                    //  handled individually
 
                     const std::vector<sal_uInt32>& rCondFormatData = static_cast<const ScCondFormatItem*>(pCondItem)->GetCondFormatData();
                     ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
@@ -2060,7 +2060,7 @@ void ScTable::FindMaxRotCol( RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCC
                                             FillMaxRot( pRowInfo, nArrCount, nX1, nX2,
                                                     nCol, nAttrRow1, nAttrRow2,
                                                     nArrY, pPattern, &pStyleSheet->GetItemSet() );
-                                            //  nArrY nicht veraendern
+                                            //  not changing nArrY
                                         }
                                     }
                                 }
@@ -2086,28 +2086,28 @@ bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCR
     sal_uInt16 nEdges = 0;
 
     if ( nCol1 == nCol2 )
-    {   // linke und rechte Spalte
+    {   // left and right column
         const sal_uInt16 n = MatrixEdgeLeft | MatrixEdgeRight;
         nEdges = aCol[nCol1].GetBlockMatrixEdges( nRow1, nRow2, n );
-        // nicht (4 und 16) oder 1 oder 32
+        // not (4 and 16) or 1 or 32
         if (nEdges && (((nEdges & n) != n) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
-            return true;        // linke oder rechte Kante fehlt oder offen
+            return true;        // left or right edge is missing or open
     }
     else
-    {   // linke Spalte
+    {   // left column
         nEdges = aCol[nCol1].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdgeLeft);
-        // nicht 4 oder 1 oder 32
+        // not 4 or 1 or 32
         if (nEdges && (((nEdges & MatrixEdgeLeft) != MatrixEdgeLeft) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
-            return true;        // linke Kante fehlt oder offen
-        // rechte Spalte
+            return true;        // left edge missing or open
+        // right column
         nEdges = aCol[nCol2].GetBlockMatrixEdges(nRow1, nRow2, MatrixEdgeRight);
-        // nicht 16 oder 1 oder 32
+        // not 16 or 1 or 32
         if (nEdges && (((nEdges & MatrixEdgeRight) != MatrixEdgeRight) || (nEdges & (MatrixEdgeInside|MatrixEdgeOpen))))
-            return true;        // rechte Kante fehlt oder offen
+            return true;        // right edge is missing or open
     }
 
     if ( nRow1 == nRow2 )
-    {   // obere und untere Zeile
+    {   // Row on top and on bottom
         bool bOpen = false;
         const sal_uInt16 n = MatrixEdgeBottom | MatrixEdgeTop;
         for ( SCCOL i=nCol1; i<=nCol2; i++)
@@ -2116,23 +2116,23 @@ bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCR
             if ( nEdges )
             {
                 if ( (nEdges & n) != n )
-                    return true;        // obere oder untere Kante fehlt
+                    return true;        // Top or bottom edge missing
                 if (nEdges & MatrixEdgeLeft)
-                    bOpen = true;       // linke Kante oeffnet, weitersehen
+                    bOpen = true;       // left edge open, continue
                 else if ( !bOpen )
-                    return true;        // es gibt was, was nicht geoeffnet wurde
+                    return true;        // Something exist that has not been opened
                 if (nEdges & MatrixEdgeRight)
-                    bOpen = false;      // rechte Kante schliesst
+                    bOpen = false;      // Close right edge
             }
         }
         if ( bOpen )
-            return true;                // es geht noch weiter
+            return true;                // continue
     }
     else
     {
         sal_uInt16 j, n;
         SCROW nR;
-        // erst obere Zeile, dann untere Zeile
+        // first rop row, then bottom row
         for ( j=0, nR=nRow1, n=8; j<2; j++, nR=nRow2, n=2 )
         {
             bool bOpen = false;
@@ -2141,20 +2141,20 @@ bool ScTable::HasBlockMatrixFragment( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCR
                 nEdges = aCol[i].GetBlockMatrixEdges( nR, nR, n );
                 if ( nEdges )
                 {
-                    // in oberere Zeile keine obere Kante bzw.
-                    // in unterer Zeile keine untere Kante
+                    // in top row no top edge respectively
+                    // in bottom row no bottom edge
                     if ( (nEdges & n) != n )
                         return true;
                     if (nEdges & MatrixEdgeLeft)
-                        bOpen = true;       // linke Kante oeffnet, weitersehen
+                        bOpen = true;       // open left edge, continue
                     else if ( !bOpen )
-                        return true;        // es gibt was, was nicht geoeffnet wurde
+                        return true;        // Something exist that has not been opened
                     if (nEdges & MatrixEdgeRight)
-                        bOpen = false;      // rechte Kante schliesst
+                        bOpen = false;      // Close right edge
                 }
             }
             if ( bOpen )
-                return true;                // es geht noch weiter
+                return true;                // continue
         }
     }
     return false;
@@ -2515,7 +2515,7 @@ const ScStyleSheet* ScTable::GetSelectionStyle( const ScMarkData& rMark, bool& r
             {
                 rFound = true;
                 if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
-                    bEqual = false;                                             // unterschiedliche
+                    bEqual = false;
                 pStyle = pNewStyle;
             }
         }
@@ -2541,7 +2541,7 @@ const ScStyleSheet* ScTable::GetAreaStyle( bool& rFound, SCCOL nCol1, SCROW nRow
         {
             rFound = true;
             if ( !pNewStyle || ( pStyle && pNewStyle != pStyle ) )
-                bEqual = false;                                             // unterschiedliche
+                bEqual = false;
             pStyle = pNewStyle;
         }
     }
@@ -2643,7 +2643,7 @@ void ScTable::ClearSelectionItems( const sal_uInt16* pWhich, const ScMarkData& r
         aCol[i].ClearSelectionItems( pWhich, rMark );
 }
 
-//  Spaltenbreiten / Zeilenhoehen
+//  Column widths / Row heights
 
 void ScTable::SetColWidth( SCCOL nCol, sal_uInt16 nNewWidth )
 {
@@ -2861,7 +2861,7 @@ sal_uLong ScTable::GetColWidth( SCCOL nStartCol, SCCOL nEndCol, bool bHiddenAsZe
     return nW;
 }
 
-sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const        // immer die eingestellte
+sal_uInt16 ScTable::GetOriginalWidth( SCCOL nCol ) const        // always the set value
 {
     OSL_ENSURE(ValidCol(nCol),"wrong column number");
 
@@ -3034,7 +3034,7 @@ sal_uInt16 ScTable::GetOriginalHeight( SCROW nRow ) const       // non-0 even if
         return (sal_uInt16) ScGlobal::nStdRowHeight;
 }
 
-//  Spalten-/Zeilen-Flags
+//  Column/Row -Flags
 
 SCROW ScTable::GetHiddenRowCount( SCROW nRow ) const
 {
@@ -3097,7 +3097,7 @@ void ScTable::DBShowRow(SCROW nRow, bool bShow)
 {
     if (ValidRow(nRow) && pRowFlags)
     {
-        //  Filter-Flag immer setzen, auch wenn Hidden unveraendert
+        //  Always set Filter-Flag, also unchanged when Hidden
         bool bChanged = SetRowHidden(nRow, nRow, !bShow);
         SetRowFiltered(nRow, nRow, !bShow);
 
@@ -3442,7 +3442,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC
 
     StartOutlineTable();
 
-                            // Zeilen
+                            // Rows
 
     UsedRowsType aUsed(0, MAXROW+1, false);
     for (nCol=nStartCol; nCol<=nEndCol; nCol++)
@@ -3497,7 +3497,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC
     }
 }
 
-                                    //  CopyData - fuer Query in anderen Bereich
+                                    //  CopyData - for Query in other range
 
 void ScTable::CopyData( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
                             SCCOL nDestCol, SCROW nDestRow, SCTAB nDestTab )
@@ -3569,7 +3569,7 @@ bool ScTable::RefVisible(ScFormulaCell* pCell)
         }
     }
 
-    return true;                        // irgendwie anders
+    return true;                        // somehow different
 }
 
 void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, OUString& rStr)
@@ -3578,7 +3578,7 @@ void ScTable::GetUpperCellString(SCCOL nCol, SCROW nRow, OUString& rStr)
     rStr = ScGlobal::pCharClass->uppercase(rStr.trim());
 }
 
-// Berechnen der Groesse der Tabelle und setzen der Groesse an der DrawPage
+// Calculate the size of the sheet and set the size on DrawPage
 
 void ScTable::SetDrawPageSize(bool bResetStreamValid, bool bUpdateNoteCaptionPos)
 {
diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx
index d673583..22528bd 100644
--- a/sc/source/core/data/table3.cxx
+++ b/sc/source/core/data/table3.cxx
@@ -1526,11 +1526,11 @@ short ScTable::CompareCell(
                         nRes = static_cast<short>( pSortCollator->compareString( aStr1, aStr2 ) );
                 }
             }
-            else if ( bStr1 )               // String <-> Zahl
-                nRes = 1;                   // Zahl vorne
-            else if ( bStr2 )               // Zahl <-> String
-                nRes = -1;                  // Zahl vorne
-            else                            // Zahlen untereinander
+            else if ( bStr1 )               // String <-> Number
+                nRes = 1;                   // Number in front
+            else if ( bStr2 )               // Number <-> String
+                nRes = -1;                  // Number in front
+            else                            // Mixed numbers
             {
                 double nVal1 = rCell1.getValue();
                 double nVal2 = rCell2.getValue();
@@ -1550,7 +1550,7 @@ short ScTable::CompareCell(
         if (!rCell2.isEmpty())
             nRes = 1;
         else
-            nRes = 0;                   // beide leer
+            nRes = 0;                   // both empty
     }
     return nRes;
 }
@@ -1655,7 +1655,7 @@ short ScTable::Compare(SCCOLROW nIndex1, SCCOLROW nIndex2) const
     return nRes;
 }
 
-bool ScTable::IsSorted( SCCOLROW nStart, SCCOLROW nEnd ) const   // ueber aSortParam
+bool ScTable::IsSorted( SCCOLROW nStart, SCCOLROW nEnd ) const   // over aSortParam
 {
     for (SCCOLROW i=nStart; i<nEnd; i++)
     {
@@ -1871,7 +1871,7 @@ void ScTable::RemoveSubTotals( ScSubTotalParam& rParam )
     SCCOL nStartCol = rParam.nCol1;
     SCROW nStartRow = rParam.nRow1 + 1;     // Header
     SCCOL nEndCol   = rParam.nCol2;
-    SCROW nEndRow    = rParam.nRow2;            // wird veraendert
+    SCROW nEndRow    = rParam.nRow2;        // will change
 
     RemoveSubTotalsHandler aFunc;
     for (SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol)
@@ -1894,7 +1894,7 @@ void ScTable::RemoveSubTotals( ScSubTotalParam& rParam )
     rParam.nRow2 -= aRows.size();
 }
 
-//  harte Zahlenformate loeschen (fuer Ergebnisformeln)
+//  Delete hard number formats (for result formulas)
 
 static void lcl_RemoveNumberFormat( ScTable* pTab, SCCOL nCol, SCROW nRow )
 {
@@ -1920,24 +1920,24 @@ typedef struct lcl_ScTable_DoSubTotals_RowEntry
     SCROW   nFuncEnd;
 } RowEntry;
 
-//      neue Zwischenergebnisse
-//      rParam.nRow2 wird veraendert !
+//      new intermediate results
+//      rParam.nRow2 is changed !
 
 bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
 {
     SCCOL nStartCol = rParam.nCol1;
     SCROW nStartRow = rParam.nRow1 + 1;     // Header
     SCCOL nEndCol   = rParam.nCol2;
-    SCROW nEndRow    = rParam.nRow2;            // wird veraendert
+    SCROW nEndRow    = rParam.nRow2;        // will change
     sal_uInt16 i;
 
-    //  Leerzeilen am Ende weglassen,
-    //  damit alle Ueberlaeufe (MAXROW) bei InsertRow gefunden werden (#35180#)
-    //  Wenn sortiert wurde, sind alle Leerzeilen am Ende.
+    //  Remove emty rows at the end
+    //  so that all exceeding (MAXROW) can be found by InsertRow (#35180#)
+    //  If sorted, all empty rows are at the end.
     SCSIZE nEmpty = GetEmptyLinesInBlock( nStartCol, nStartRow, nEndCol, nEndRow, DIR_BOTTOM );
     nEndRow -= nEmpty;
 
-    sal_uInt16 nLevelCount = 0;             // Anzahl Gruppierungen
+    sal_uInt16 nLevelCount = 0;             // Number of levels
     bool bDoThis = true;
     for (i=0; i<MAXSUBTOTAL && bDoThis; i++)
         if (rParam.bGroupActive[i])
@@ -1945,15 +1945,14 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
         else
             bDoThis = false;
 
-    if (nLevelCount==0)                 // nichts tun
+    if (nLevelCount==0)                 // do nothing
         return true;
 
-    SCCOL*          nGroupCol = rParam.nField;  // Spalten nach denen
-                                                // gruppiert wird
+    SCCOL*          nGroupCol = rParam.nField;  // columns which will be used when grouping
 
-    //  Durch (leer) als eigene Kategorie muss immer auf
-    //  Teilergebniszeilen aus den anderen Spalten getestet werden
-    //  (frueher nur, wenn eine Spalte mehrfach vorkam)
+    //  With (blank) as a separate category, subtotal rows from
+    //  the other columns must always be tested
+    //  (previously only when a column occured more than once)
     bool bTestPrevSub = ( nLevelCount > 1 );
 
     OUString  aSubString;
@@ -1961,7 +1960,7 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
 
     bool bIgnoreCase = !rParam.bCaseSens;
 
-    OUString *pCompString[MAXSUBTOTAL];               // Pointer wegen Compiler-Problemen
+    OUString *pCompString[MAXSUBTOTAL];               // Pointer due to compiler problemens
     for (i=0; i<MAXSUBTOTAL; i++)
         pCompString[i] = new OUString;
 
@@ -1970,7 +1969,7 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
     ScStyleSheet* pStyle = static_cast<ScStyleSheet*>(pDocument->GetStyleSheetPool()->Find(
                                 ScGlobal::GetRscString(STR_STYLENAME_RESULT), SFX_STYLE_FAMILY_PARA ));
 
-    bool bSpaceLeft = true;                                         // Erfolg beim Einfuegen?
+    bool bSpaceLeft = true;                                         // Succsess when inserting?
 
     // For performance reasons collect formula entries so their
     // references don't have to be tested for updates each time a new row is
@@ -1978,7 +1977,7 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
     RowEntry aRowEntry;
     ::std::vector< RowEntry > aRowVector;
 
-    for (sal_uInt16 nLevel=0; nLevel<=nLevelCount && bSpaceLeft; nLevel++)      // incl. Gesamtergebnis
+    for (sal_uInt16 nLevel=0; nLevel<=nLevelCount && bSpaceLeft; nLevel++)      // including grand total
     {
         bool bTotal = ( nLevel == nLevelCount );
         aRowEntry.nGroupNo = bTotal ? 0 : (nLevelCount-nLevel-1);
@@ -1988,7 +1987,7 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
         // result functions
         ScSubTotalFunc* eResFunc = rParam.pFunctions[aRowEntry.nGroupNo];
 
-        if (nResCount > 0)                                      // sonst nur sortieren
+        if (nResCount > 0)                                      // otherwise only sort
         {
             for (i=0; i<=aRowEntry.nGroupNo; i++)
             {
@@ -1997,9 +1996,9 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
                     *pCompString[i] = ScGlobal::pCharClass->uppercase( aSubString );
                 else
                     *pCompString[i] = aSubString;
-            }                                                   // aSubString bleibt auf dem letzten stehen
+            }                                                   // aSubString stays on the last
 
-            bool bBlockVis = false;             // Gruppe eingeblendet?
+            bool bBlockVis = false;             // group visible?
             aRowEntry.nSubStartRow = nStartRow;
             for (SCROW nRow=nStartRow; nRow<=nEndRow+1 && bSpaceLeft; nRow++)
             {
@@ -2017,8 +2016,8 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
                             GetString( nGroupCol[i], nRow, aString );
                             if (bIgnoreCase)
                                 aString = ScGlobal::pCharClass->uppercase(aString);
-                            //  wenn sortiert, ist "leer" eine eigene Gruppe
-                            //  sonst sind leere Zellen unten erlaubt
+                            //  when sorting, blanks are seperate group
+                            //  otherwise blak cells are allowed below
                             bChanged = ( ( !aString.isEmpty() || rParam.bDoSort ) &&
                                             aString != *pCompString[i] );
                         }
@@ -2070,10 +2069,10 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
                         // collect formula positions
                         aRowVector.push_back( aRowEntry );
 
-                        if (bTotal)     // "Gesamtergebnis"
+                        if (bTotal)     // "Grand total"
                             aOutString = ScGlobal::GetRscString( STR_TABLE_GESAMTERGEBNIS );
                         else
-                        {               // " Ergebnis"
+                        {               // "Result"
                             aOutString = aSubString;
                             if (aOutString.isEmpty())
                                 aOutString = ScGlobal::GetRscString( STR_EMPTYDATA );
@@ -2156,7 +2155,6 @@ bool ScTable::DoSubTotals( ScSubTotalParam& rParam )
             {
                 ApplyStyle( nResCols[nResult], iEntry->nDestRow, *pStyle );
 
-                //  Zahlformat loeschen
                 lcl_RemoveNumberFormat( this, nResCols[nResult], iEntry->nDestRow );
             }
         }
@@ -2751,18 +2749,18 @@ void ScTable::TopTenQuery( ScQueryParam& rParam )
                 QuickSort( pArray.get(), nRow1, rParam.nRow2 );
                 ScSortInfo** ppInfo = pArray->GetFirstArray();
                 SCSIZE nValidCount = nCount;
-                // keine Note-/Leerzellen zaehlen, sind ans Ende sortiert
+                // Don't count note or blank cells, they are sorted at the end
                 while (nValidCount > 0 && ppInfo[nValidCount-1]->maCell.isEmpty())
                     nValidCount--;
-                // keine Strings zaehlen, sind zwischen Value und Leer
+                // Don't count Strings, they are between Value and blank
                 while (nValidCount > 0 && ppInfo[nValidCount-1]->maCell.hasString())
                     nValidCount--;
                 if ( nValidCount > 0 )
                 {
                     if ( rItem.meType == ScQueryEntry::ByString )
-                    {   // dat wird nix
+                    {   // this will be nothing
                         rItem.meType = ScQueryEntry::ByValue;
-                        rItem.mfVal = 10;   // 10 bzw. 10%
+                        rItem.mfVal = 10;   // 10 and 10% respectively
                     }
                     SCSIZE nVal = (rItem.mfVal >= 1 ? static_cast<SCSIZE>(rItem.mfVal) : 1);
                     SCSIZE nOffset = 0;
@@ -2953,9 +2951,9 @@ SCSIZE ScTable::Query(ScQueryParam& rParamOrg, bool bKeepSub)
     SCROW nRealRow2 = aParam.nRow2;
     for (SCROW j = aParam.nRow1 + nHeader; j <= nRealRow2; ++j)
     {
-        bool bResult;                                   // Filterergebnis
+        bool bResult;                                   // Filter result
         bool bValid = ValidQuery(j, aParam);
-        if (!bValid && bKeepSub)                        // Subtotals stehenlassen
+        if (!bValid && bKeepSub)                        // Keep subtotals
         {
             for (SCCOL nCol=aParam.nCol1; nCol<=aParam.nCol2 && !bValid; nCol++)
             {
@@ -3039,7 +3037,7 @@ bool ScTable::CreateExcelQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow
     SCTAB   nDBTab = (rQueryParam.nTab == SCTAB_MAX ? nTab : rQueryParam.nTab);
     SCROW   nDBRow1 = rQueryParam.nRow1;
     SCCOL   nDBCol2 = rQueryParam.nCol2;
-    // Erste Zeile muessen Spaltenkoepfe sein
+    // First row must be column header
     while (bValid && (nCol <= nCol2))
     {
         OUString aQueryStr;
@@ -3140,7 +3138,7 @@ bool ScTable::CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2
         ScQueryEntry& rEntry = rQueryParam.GetEntry(nIndex);
 
         bValid = false;
-        // Erste Spalte UND/ODER
+        // First column AND/OR
         if (nIndex > 0)
         {
             GetUpperCellString(nCol1, nRow, aCellStr);
@@ -3155,7 +3153,7 @@ bool ScTable::CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2
                 bValid = true;
             }
         }
-        // Zweite Spalte FeldName
+        // Second column field name
         if ((nIndex < 1) || bValid)
         {
             bFound = false;
@@ -3177,7 +3175,7 @@ bool ScTable::CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2
                     bValid = false;
             }
         }
-        // Dritte Spalte Operator =<>...
+        // Third column operator =<>...
         if (bValid)
         {
             bFound = false;
@@ -3202,7 +3200,7 @@ bool ScTable::CreateStarQuery(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2
                 rEntry.eOp = SC_EQUAL;
 
         }
-        // Vierte Spalte Wert
+        // Forth column values
         if (bValid)
         {
             OUString aStr;
@@ -3227,16 +3225,16 @@ bool ScTable::CreateQueryParam(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow
     for (i=0; i < nCount; i++)
         rQueryParam.GetEntry(i).Clear();
 
-    // Standard QueryTabelle
+    // Standard query tabel
     bool bValid = CreateStarQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
-    // Excel QueryTabelle
+    // Excel Query tabel
     if (!bValid)
         bValid = CreateExcelQuery(nCol1, nRow1, nCol2, nRow2, rQueryParam);
 
     nCount = rQueryParam.GetEntryCount();
     if (bValid)
     {
-        //  bQueryByString muss gesetzt sein
+        //  bQueryByString must be set
         for (i=0; i < nCount; i++)
             rQueryParam.GetEntry(i).GetQueryItem().meType = ScQueryEntry::ByString;
     }
commit 3743302fa26b0b3890b7113c30ec94755868a2f7
Author: Yousuf Philips <philipz85 at hotmail.com>
Date:   Fri Feb 13 00:08:35 2015 +0400

    tdf#83955 enable insert comment and rearrange buttons
    
    Change-Id: I57da2e38a555c75f674885d736a82adbc8f81224
    Reviewed-on: https://gerrit.libreoffice.org/14450
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/sw/uiconfig/swriter/toolbar/changes.xml b/sw/uiconfig/swriter/toolbar/changes.xml
index 47bad1f..3ba4ad5 100644
--- a/sw/uiconfig/swriter/toolbar/changes.xml
+++ b/sw/uiconfig/swriter/toolbar/changes.xml
@@ -27,10 +27,10 @@
  <toolbar:toolbaritem xlink:href=".uno:RejectTrackedChange" toolbar:text="Reject" toolbar:helpid="10626"/>
  <toolbar:toolbaritem xlink:href=".uno:AcceptTrackedChanges" toolbar:text="List" toolbar:helpid="10622"/>
  <toolbar:toolbarseparator/>
- <toolbar:toolbaritem xlink:href=".uno:CommentChangeTracking" toolbar:text="Comment" toolbar:helpid="10625"/>
- <toolbar:toolbaritem xlink:href=".uno:ProtectTraceChangeMode" toolbar:text="Protect" toolbar:helpid="10625"/>
+ <toolbar:toolbaritem xlink:href=".uno:InsertAnnotation" toolbar:text="Regular Comment" toolbar:helpid="10625"/>

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list