diff --git a/MobileOrg/src/main/AndroidManifest.xml b/MobileOrg/src/main/AndroidManifest.xml
index 2c306100..d4ae0c46 100644
--- a/MobileOrg/src/main/AndroidManifest.xml
+++ b/MobileOrg/src/main/AndroidManifest.xml
@@ -29,7 +29,7 @@
android:resource="@xml/widget_mobileorg" />
-
+
@@ -61,6 +61,7 @@
android:theme="@style/ActionModeAppTheme">
+
@@ -70,10 +71,10 @@
+ android:theme="@style/AppTheme.NoActionBar" />
+ android:theme="@style/ActionModeAppTheme" />
+ android:theme="@style/AppTheme.NoActionBar" />
+ android:theme="@style/AppTheme.NoActionBar" />
+ android:label="WebDAV Settings" />
+ android:label="SDCard Settings" />
+ android:label="Scp Settings" />
+ android:label="Ubuntu One Settings" />
+ android:theme="@style/ActionModeAppTheme" />
-
+
-
-
+
+
-
+
-
-
+
+
+ android:theme="@style/AppTheme.NoActionBar" />
+
-
-
+
\ No newline at end of file
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/ConflictResolverActivity.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/ConflictResolverActivity.java
new file mode 100644
index 00000000..3f78ed14
--- /dev/null
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/ConflictResolverActivity.java
@@ -0,0 +1,96 @@
+package com.matburt.mobileorg2.Gui.Outline;
+
+import android.content.Intent;
+import android.support.v4.app.NavUtils;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.support.v7.widget.Toolbar;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.EditText;
+
+import com.matburt.mobileorg2.OrgData.OrgContract;
+import com.matburt.mobileorg2.OrgData.OrgFile;
+import com.matburt.mobileorg2.OrgData.OrgProviderUtils;
+import com.matburt.mobileorg2.OrgNodeListActivity;
+import com.matburt.mobileorg2.R;
+import com.matburt.mobileorg2.Synchronizers.JGitWrapper;
+import com.matburt.mobileorg2.Synchronizers.SynchronizerManager;
+import com.matburt.mobileorg2.util.OrgFileNotFoundException;
+import com.matburt.mobileorg2.util.OrgUtils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+
+public class ConflictResolverActivity extends AppCompatActivity {
+
+ EditText editText;
+ String filename;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_conflict_resolver);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar);
+ setSupportActionBar(toolbar);
+
+ // Show the Up button in the action bar.
+ ActionBar actionBar = getSupportActionBar();
+
+
+
+ if (savedInstanceState == null) {
+ // Create the detail fragment and add it to the activity
+ // using a fragment transaction.
+ Bundle arguments = new Bundle();
+ Long nodeId = getIntent().getLongExtra(OrgContract.NODE_ID, -1);
+
+ editText = (EditText)findViewById(R.id.conflict_resolver_text);
+ try {
+ OrgFile file = new OrgFile(nodeId, getContentResolver());
+ if (actionBar != null) {
+ actionBar.setTitle(file.name);
+ }
+
+ String dir = SynchronizerManager.getInstance(null,null,null).getSyncher().getAbsoluteFilesDir(this);
+ this.filename = dir+"/"+file.filename;
+ editText.setText(OrgUtils.readAll(this.filename));
+
+ } catch (OrgFileNotFoundException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.edit_node_menu, menu);
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.edit_menu_cancel:
+ NavUtils.navigateUpTo(this, new Intent(this, OrgNodeListActivity.class));
+ return true;
+ case R.id.edit_menu_ok:
+ if(this.filename!=null && !this.filename.equals("")){
+ OrgUtils.writeToFile(this.filename, editText.getText().toString());
+ new JGitWrapper.MergeTask(this).execute();
+ }
+ NavUtils.navigateUpTo(this, new Intent(this, OrgNodeListActivity.class));
+ return true;
+ }
+ return false;
+ }
+
+
+}
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/OutlineAdapter.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/OutlineAdapter.java
index e1e14762..0d95e6c7 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/OutlineAdapter.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/Gui/Outline/OutlineAdapter.java
@@ -35,13 +35,13 @@
public class OutlineAdapter extends RecyclerView.Adapter {
private final AppCompatActivity activity;
- public List items = new ArrayList<>();
+ public List items = new ArrayList<>();
ActionMode actionMode;
private ContentResolver resolver;
private boolean mTwoPanes = false;
private SparseBooleanArray selectedItems;
// Number of added items. Here it is two: Agenda and Todos.
- private int numExtraItems = 2;
+ final private int numExtraItems = 2;
private ActionMode.Callback mDeleteMode = new ActionMode.Callback() {
@Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
@@ -110,11 +110,10 @@ public OutlineAdapter(AppCompatActivity activity) {
public void refresh() {
clear();
- for (OrgNode node : OrgProviderUtils.getOrgNodeChildren(-1, resolver)){
- add(node);
+ for (OrgFile file : OrgProviderUtils.getFiles(resolver)){
+ add(file);
}
-
notifyDataSetChanged();
}
@@ -130,7 +129,11 @@ public void refresh() {
@Override
public void onBindViewHolder(final OutlineItem holder, final int position) {
int positionInItems = position - numExtraItems;
-
+ OrgFile file = null;
+ try{
+ file = items.get(positionInItems);
+ } catch(ArrayIndexOutOfBoundsException ignored){}
+ final boolean conflict = (file != null && file.getState() == OrgFile.State.kConflict);
String title;
if(position == 0) {
title = activity.getResources().getString(R.string.menu_todos);
@@ -142,6 +145,15 @@ public void onBindViewHolder(final OutlineItem holder, final int position) {
holder.titleView.setText(title);
+ TextView comment = (TextView)holder.mView.findViewById(R.id.comment);
+
+ if (conflict) {
+ comment.setText(R.string.conflict);
+ comment.setVisibility(View.VISIBLE);
+ } else {
+ comment.setVisibility(View.GONE);
+ }
+
holder.mView.setActivated(selectedItems.get(positionInItems, false));
final long itemId = getItemId(position);
@@ -165,7 +177,15 @@ public void onClick(View v) {
// TODO: add agenda fragment
} else {
Context context = v.getContext();
- Intent intent = new Intent(context, OrgNodeDetailActivity.class);
+ Intent intent;
+
+ // Special activity for conflicted file
+ if(conflict){
+ intent = new Intent(context, ConflictResolverActivity.class);
+ } else {
+ intent = new Intent(context, OrgNodeDetailActivity.class);
+ }
+
if(position == 0){
intent.putExtra(OrgContract.NODE_ID, OrgContract.TODO_ID);
@@ -208,14 +228,14 @@ public void clear() {
this.items.clear();
}
- public void add(OrgNode node) {
- this.items.add(node);
+ public void add(OrgFile file) {
+ this.items.add(file);
}
@Override
public long getItemId(int position) {
if(position < numExtraItems) return -1;
- OrgNode node = items.get(position - numExtraItems);
+ OrgFile node = items.get(position - numExtraItems);
return node.id;
}
@@ -237,7 +257,6 @@ public void toggleSelection(int pos) {
if(countAfter > 0 && actionMode != null){
actionMode.invalidate();
}
-
}
public void clearSelections() {
@@ -262,16 +281,8 @@ private void deleteSelectedFiles(){
List selectedItems = getSelectedItems();
for(Integer num: selectedItems){
num -= numExtraItems;
- OrgNode node = items.get(num);
- try {
- OrgFile file = new OrgFile(node.fileId, resolver);
- file.removeFile(activity);
- } catch (OrgFileNotFoundException e) {
- e.printStackTrace();
- }
-
- node.deleteNode(activity);
- Log.v("selection","deleting : "+items.get(num).name);
+ OrgFile file = items.get(num);
+ file.removeFile(activity);
}
refresh();
actionMode.finish();
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgContract.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgContract.java
index 12330d2b..c3c539da 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgContract.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgContract.java
@@ -32,7 +32,7 @@ interface FilesColumns {
String ID = "_id";
String NAME = "name";
String FILENAME = "filename";
- String CHECKSUM = "checksum";
+ String COMMENT = "comment";
String NODE_ID = "node_id";
}
@@ -128,7 +128,7 @@ public static class Files implements FilesColumns {
BASE_CONTENT_URI.buildUpon().appendPath(PATH_FILES).build();
public static final String[] DEFAULT_COLUMNS = { ID, NAME, FILENAME,
- CHECKSUM, NODE_ID };
+ COMMENT, NODE_ID };
public static final String DEFAULT_SORT = NAME + " ASC";
public static String getId(Uri uri) {
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgDatabase.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgDatabase.java
index cf332351..87569c7a 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgDatabase.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgDatabase.java
@@ -5,12 +5,9 @@
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteStatement;
-import android.util.Log;
import com.matburt.mobileorg2.OrgData.OrgContract.OrgData;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
import java.util.HashMap;
public class OrgDatabase extends SQLiteOpenHelper {
@@ -24,74 +21,22 @@ public class OrgDatabase extends SQLiteOpenHelper {
private int orgdata_priorityColumn;
private int orgdata_parentidColumn;
private int orgdata_fileidColumn;
- private int orgdata_levelColumn;
- private int orgdata_positionColumn;
+ private int orgdata_levelColumn;
+ private int orgdata_positionColumn;
private InsertHelper orgdataInsertHelper;
private SQLiteStatement addPayloadStatement;
private SQLiteStatement addTimestampsStatement;
-
-
- public interface PrioritiesTable{
- String tableName = "priorities";
- String[] id = {"_id", "integer primary key autoincrement"};
- String[] name = {"name", "text"};
- }
-
- public interface FilesTable{
- String tableName = "files";
- String[] id = {"_id", "integer primary key autoincrement"};
- String[] name = {"name", "text"};
- String[] node_id = {"node_id", "integer"};
- String[] filename = {"filename", "text"};
- String[] comment = {"comment", "text)"};
- }
-
-
- public interface TodoTable{
- String tableName = "todos";
- String[] id = {"_id", "integer primary key autoincrement"};
- String[] name = {"name", "text"};
- String[] todogroup = {"todogroup", "integer"};
- String[] isdone = {"isdone", "integer", "default 0"};
- String[] todoConstrain = {"UNIQUE(todogroup, name) ON CONFLICT IGNORE"};
- }
-
- public interface TagsTable{
- String tableName = "files";
- String[] id = {"_id", "integer primary key autoincrement"};
- String[] name = {"name", "text"};
- String[] taggroup = {"taggroup", "integer"};
+ public interface Tables {
+ String EDITS = "edits";
+ String FILES = "files";
+ String PRIORITIES = "priorities";
+ String TAGS = "tags";
+ String TODOS = "todos";
+ String ORGDATA = "orgdata";
}
- public interface EditsTable{
- String tableName = "edits";
- String[] id = {"_id", "integer primary key autoincrement"};
- String[] type = {"type", "text"};
- String[] title = {"title", "text"};
- String[] data_id = {"data_id", "integer"};
- String[] old_value = {"old_value", "text"};
- String[] new_value = {"new_value", "text"};
- String[] changed = {"changed", "integer)"};
- }
-
- public interface OrgDataTable{
- String tableName = "orgdata";
- String[] id = {"_id", "integer primary key autoincrement"};
- String[] name = {"name", "text"};
- String[] parent_id = {"parent_id", "integer", "default -1"};
- String[] file_id = {"file_id", "integer"};
- String[] level = {"level", "integer", "default 0"};
- String[] priority = {"priority", "text"};
- String[] todo = {"todo", "text"};
- String[] tags = {"tags", "text"};
- String[] tags_inherited = {"tags_inherited", "text"};
- String[] payload = {"payload", "text"};
- String[] position = {"position", "integer"};
- String[] scheduled = {"scheduled", "integer", "default -1"};
- String[] deadline = {"deadline", "integer", "default -1"};
- }
private static OrgDatabase mInstance = null;
public static OrgDatabase getInstance(Context context){
@@ -105,42 +50,78 @@ private OrgDatabase(Context context) {
@Override
public void onCreate(SQLiteDatabase db) {
- Log.v("swag","megaswag : " + new Table().createDB());
-
+ db.execSQL("CREATE TABLE IF NOT EXISTS files("
+ + "_id integer primary key autoincrement,"
+ + "node_id integer,"
+ + "filename text,"
+ + "name text,"
+ + "comment text)");
+ db.execSQL("CREATE TABLE IF NOT EXISTS todos("
+ + "_id integer primary key autoincrement,"
+ + "todogroup integer,"
+ + "name text,"
+ + "isdone integer default 0,"
+ + "UNIQUE(todogroup, name) ON CONFLICT IGNORE)");
+ db.execSQL("CREATE TABLE IF NOT EXISTS priorities("
+ + "_id integer primary key autoincrement,"
+ + "name text)");
+ db.execSQL("CREATE TABLE IF NOT EXISTS tags("
+ + "_id integer primary key autoincrement,"
+ + "taggroup integer,"
+ + "name text)");
+ db.execSQL("CREATE TABLE IF NOT EXISTS edits("
+ + "_id integer primary key autoincrement,"
+ + "type text,"
+ + "title text,"
+ + "data_id integer,"
+ + "old_value text,"
+ + "new_value text,"
+ + "changed integer)");
+ db.execSQL("CREATE TABLE IF NOT EXISTS orgdata ("
+ + "_id integer primary key autoincrement,"
+ + "parent_id integer default -1,"
+ + "file_id integer,"
+ + "level integer default 0,"
+ + "priority text,"
+ + "todo text,"
+ + "tags text,"
+ + "tags_inherited text,"
+ + "payload text,"
+ + "name text,"
+ + "position integer,"
+ + "scheduled integer default -1,"
+ + "deadline integer default -1)");
}
-
-
-
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (newVersion) {
- case 4:
- db.execSQL("DROP TABLE IF EXISTS priorities");
- db.execSQL("DROP TABLE IF EXISTS files");
- db.execSQL("DROP TABLE IF EXISTS todos");
- db.execSQL("DROP TABLE IF EXISTS edits");
- db.execSQL("DROP TABLE IF EXISTS orgdata");
- break;
-
- case 5:
- db.execSQL("alter table orgdata add tags_inherited text");
- break;
+ case 4:
+ db.execSQL("DROP TABLE IF EXISTS priorities");
+ db.execSQL("DROP TABLE IF EXISTS files");
+ db.execSQL("DROP TABLE IF EXISTS todos");
+ db.execSQL("DROP TABLE IF EXISTS edits");
+ db.execSQL("DROP TABLE IF EXISTS orgdata");
+ break;
+
+ case 5:
+ db.execSQL("alter table orgdata add tags_inherited text");
+ break;
}
onCreate(db);
}
public long fastInsertNode(OrgNode node) {
prepareOrgdataInsert();
- orgdataInsertHelper.bind(orgdata_parentidColumn, node.parentId);
+ orgdataInsertHelper.bind(orgdata_parentidColumn, node.parentId);
orgdataInsertHelper.bind(orgdata_nameColumn, node.name);
orgdataInsertHelper.bind(orgdata_todoColumn, node.todo);
orgdataInsertHelper.bind(orgdata_priorityColumn, node.priority);
orgdataInsertHelper.bind(orgdata_fileidColumn, node.fileId);
orgdataInsertHelper.bind(orgdata_tagsColumn, node.tags);
orgdataInsertHelper.bind(orgdata_tagsInheritedColumn, node.tags_inherited);
- orgdataInsertHelper.bind(orgdata_levelColumn, node.level);
- orgdataInsertHelper.bind(orgdata_positionColumn, node.position);
+ orgdataInsertHelper.bind(orgdata_levelColumn, node.level);
+ orgdataInsertHelper.bind(orgdata_positionColumn, node.position);
return orgdataInsertHelper.execute();
}
@@ -157,21 +138,20 @@ public void fastInsertNodePayload(Long id, final String payload, final HashMap res = OrgNodeTree.getFullNodeArray(tree, true);
- for (OrgNode node : res) {
- Log.v("content","content");
- Log.v("content",node.toString());
- content += FileUtils.stripLastNewLine(node.toString()) + "\n";
- }
-
- file.updateFile(content, context);
+ file.updateFile(file.toString(resolver), context);
} catch (OrgFileNotFoundException e) {
e.printStackTrace();
- } catch (OrgNodeNotFoundException e) {
- e.printStackTrace();
}
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgFile.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgFile.java
index 07ee7dfc..9a199730 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgFile.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgFile.java
@@ -11,12 +11,14 @@
import com.matburt.mobileorg2.OrgData.OrgContract.OrgData;
import com.matburt.mobileorg2.Synchronizers.Synchronizer;
import com.matburt.mobileorg2.Synchronizers.SynchronizerManager;
+import com.matburt.mobileorg2.util.FileUtils;
import com.matburt.mobileorg2.util.OrgFileNotFoundException;
import com.matburt.mobileorg2.util.OrgNodeNotFoundException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.util.ArrayList;
public class OrgFile {
public static final String CAPTURE_FILE = "mobileorg.org";
@@ -26,11 +28,17 @@ public class OrgFile {
public String filename = "";
public String name = "";
+ public String comment = "";
public boolean includeInOutline = true;
public long id = -1;
public long nodeId = -1;
+ public enum State {
+ kOK,
+ kConflict
+ }
+
public OrgFile() {
}
@@ -71,20 +79,26 @@ public OrgFile(String filename, ContentResolver resolver) throws OrgFileNotFound
cursor.close();
}
+
public void set(Cursor cursor) throws OrgFileNotFoundException {
if (cursor != null && cursor.getCount() > 0) {
if (cursor.isBeforeFirst() || cursor.isAfterLast())
cursor.moveToFirst();
- this.name = cursor.getString(cursor.getColumnIndexOrThrow(Files.NAME));
- this.filename = cursor.getString(cursor.getColumnIndexOrThrow(Files.FILENAME));
+ this.name = OrgProviderUtils.getNonNullString(cursor,
+ cursor.getColumnIndexOrThrow(Files.NAME));
+ this.filename = OrgProviderUtils.getNonNullString(cursor,
+ cursor.getColumnIndexOrThrow(Files.FILENAME));
this.id = cursor.getLong(cursor.getColumnIndexOrThrow(Files.ID));
this.nodeId = cursor.getLong(cursor.getColumnIndexOrThrow(Files.NODE_ID));
+ this.comment = OrgProviderUtils.getNonNullString(cursor,
+ cursor.getColumnIndexOrThrow(Files.COMMENT));
} else {
throw new OrgFileNotFoundException(
"Failed to create OrgFile from cursor");
}
}
+
public boolean doesFileExist(ContentResolver resolver) {
Cursor cursor = resolver.query(Files.buildFilenameUri(filename),
Files.DEFAULT_COLUMNS, null, null, null);
@@ -207,7 +221,7 @@ private long removeFileNode(ContentResolver resolver) {
* @param values
* @return
*/
- private long updateFileNode(ContentResolver resolver, ContentValues values) {
+ public long updateFileInDB(ContentResolver resolver, ContentValues values) {
return resolver.update(Files.buildIdUri(id), values, Files.NAME + "=? AND "
+ Files.FILENAME + "=?", new String[]{name, filename});
}
@@ -237,4 +251,32 @@ public String getFilePath(Context context) {
Synchronizer synchronizer = SynchronizerManager.getInstance(null, null, null).getSyncher();
return synchronizer.getAbsoluteFilesDir(context) + "/" + filename;
}
+
+ /**
+ * Query the state of the file (conflicted or not)
+ * @return
+ */
+ public State getState(){
+ return comment.equals("conflict") ? State.kConflict : State.kOK;
+ }
+
+
+ public String toString(ContentResolver resolver) {
+ String result = "";
+ OrgNode root = null;
+ try {
+ root = new OrgNode(nodeId, resolver);
+ OrgNodeTree tree = new OrgNodeTree(root, resolver);
+ ArrayList res = OrgNodeTree.getFullNodeArray(tree, true);
+ for (OrgNode node : res) {
+ Log.v("content", "content");
+ Log.v("content", node.toString());
+ result += FileUtils.stripLastNewLine(node.toString()) + "\n";
+ }
+ } catch (OrgNodeNotFoundException e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
}
+
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProvider.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProvider.java
index b5c32098..67989879 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProvider.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProvider.java
@@ -13,6 +13,7 @@
import com.matburt.mobileorg2.OrgData.OrgContract.Files;
import com.matburt.mobileorg2.OrgData.OrgContract.OrgData;
import com.matburt.mobileorg2.OrgData.OrgContract.Search;
+import com.matburt.mobileorg2.OrgData.OrgDatabase.Tables;
import com.matburt.mobileorg2.util.SelectionBuilder;
public class OrgProvider extends ContentProvider {
@@ -130,67 +131,66 @@ public String getType(Uri uri) {
private SelectionBuilder buildSelectionFromUri(Uri uri) {
final SelectionBuilder builder = new SelectionBuilder();
-// switch (uriMatcher.match(uri)) {
-// case ORGDATA:
-// return builder.table(Tables.ORGDATA);
-// case ORGDATA_ID:
-// return builder.table(Tables.ORGDATA).where(OrgData.ID + "=?", OrgData.getId(uri));
-// case ORGDATA_PARENT:
-// return builder.table(Tables.ORGDATA).where(OrgData.ID + "=?", OrgData.getId(uri));
-// case ORGDATA_CHILDREN:
-// return builder.table(Tables.ORGDATA).where(OrgData.PARENT_ID + "=?", OrgData.getId(uri));
-// case FILES:
-// return builder.table(Tables.FILES);
-// case FILES_ID:
-// return builder.table(Tables.FILES).where(Files.ID + "=?", Files.getId(uri));
-// case FILES_FILENAME:
-// return builder.table(Tables.FILES).where(Files.FILENAME + "=?", Files.getFilename(uri));
-// case EDITS:
-// return builder.table(Tables.EDITS);
-// case EDITS_ID:
-// return builder.table(Tables.EDITS).where(Edits.ID + "=?", Edits.getId(uri));
-// case TAGS:
-// return builder.table(Tables.TAGS);
-// case TODOS:
-// return builder.table(Tables.TODOS);
-// case PRIORITIES:
-// return builder.table(Tables.PRIORITIES);
-// case SEARCH:
-// final String search = Search.getSearchTerm(uri);
-// return builder.table(Tables.ORGDATA).where("name LIKE %?%", search);
-// default:
-// throw new IllegalArgumentException("Unknown URI " + uri);
-// }
- return null;
+ switch (uriMatcher.match(uri)) {
+ case ORGDATA:
+ return builder.table(Tables.ORGDATA);
+ case ORGDATA_ID:
+ return builder.table(Tables.ORGDATA).where(OrgData.ID + "=?", OrgData.getId(uri));
+ case ORGDATA_PARENT:
+ return builder.table(Tables.ORGDATA).where(OrgData.ID + "=?", OrgData.getId(uri));
+ case ORGDATA_CHILDREN:
+ return builder.table(Tables.ORGDATA).where(OrgData.PARENT_ID + "=?", OrgData.getId(uri));
+ case FILES:
+ return builder.table(Tables.FILES);
+ case FILES_ID:
+ return builder.table(Tables.FILES).where(Files.ID + "=?", Files.getId(uri));
+ case FILES_FILENAME:
+ return builder.table(Tables.FILES).where(Files.FILENAME + "=?", Files.getFilename(uri));
+ case EDITS:
+ return builder.table(Tables.EDITS);
+ case EDITS_ID:
+ return builder.table(Tables.EDITS).where(Edits.ID + "=?", Edits.getId(uri));
+ case TAGS:
+ return builder.table(Tables.TAGS);
+ case TODOS:
+ return builder.table(Tables.TODOS);
+ case PRIORITIES:
+ return builder.table(Tables.PRIORITIES);
+ case SEARCH:
+ final String search = Search.getSearchTerm(uri);
+ return builder.table(Tables.ORGDATA).where("name LIKE %?%", search);
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
}
private String getTableNameFromUri(Uri uri) {
String tableName = null;
-// switch(uriMatcher.match(uri)) {
-// case ORGDATA:
-// tableName = Tables.ORGDATA;
-// break;
-// case FILES:
-// tableName = Tables.FILES;
-// break;
-// case EDITS:
-// tableName = Tables.EDITS;
-// break;
-// case TAGS:
-// tableName = Tables.TAGS;
-// break;
-// case TODOS:
-// tableName = Tables.TODOS;
-// break;
-// case PRIORITIES:
-// tableName = Tables.PRIORITIES;
-// break;
-//
-// default:
-// throw new IllegalArgumentException("Unknown URI " + uri);
-// }
-
+ switch(uriMatcher.match(uri)) {
+ case ORGDATA:
+ tableName = Tables.ORGDATA;
+ break;
+ case FILES:
+ tableName = Tables.FILES;
+ break;
+ case EDITS:
+ tableName = Tables.EDITS;
+ break;
+ case TAGS:
+ tableName = Tables.TAGS;
+ break;
+ case TODOS:
+ tableName = Tables.TODOS;
+ break;
+ case PRIORITIES:
+ tableName = Tables.PRIORITIES;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
return tableName;
}
}
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProviderUtils.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProviderUtils.java
index 6146cabf..ec6281d5 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProviderUtils.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/OrgData/OrgProviderUtils.java
@@ -33,6 +33,7 @@ public static List getFileNodes(Context context){
return OrgProviderUtils.getOrgNodeChildren(-1, context.getContentResolver());
}
+
public static ArrayList getFilenames(ContentResolver resolver) {
ArrayList result = new ArrayList();
@@ -55,6 +56,39 @@ public static ArrayList getFilenames(ContentResolver resolver) {
}
+ /**
+ * Query the DB for the list of files
+ * @param resolver
+ * @return
+ */
+ public static ArrayList getFiles(ContentResolver resolver) {
+ ArrayList result = new ArrayList<>();
+
+ Cursor cursor = resolver.query(Files.CONTENT_URI, Files.DEFAULT_COLUMNS,
+ null, null, Files.DEFAULT_SORT);
+ if(cursor == null) return result;
+ cursor.moveToFirst();
+
+ while (!cursor.isAfterLast()) {
+ OrgFile orgFile = new OrgFile();
+
+ try {
+ orgFile.set(cursor);
+ result.add(orgFile);
+ } catch (OrgFileNotFoundException e) {}
+ cursor.moveToNext();
+ }
+
+ cursor.close();
+ return result;
+ }
+
+ public static String getNonNullString(Cursor cursor, int index){
+ String result = cursor.getString(index);
+ return result!=null ? result : "";
+ }
+
+
public static void addTodos(HashMap todos,
ContentResolver resolver) {
if(todos == null) return;
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/Synchronizers/JGitWrapper.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/Synchronizers/JGitWrapper.java
index cb4eaf31..0d0648a8 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/Synchronizers/JGitWrapper.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/Synchronizers/JGitWrapper.java
@@ -1,31 +1,23 @@
package com.matburt.mobileorg2.Synchronizers;
import android.app.Activity;
-import android.app.Application;
-import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
import android.os.AsyncTask;
-import android.os.Bundle;
-import android.support.v4.app.FragmentActivity;
-import android.support.v7.app.AlertDialog;
import android.util.Log;
-import android.widget.Button;
import android.widget.Toast;
-import com.matburt.mobileorg2.OrgData.OrgContract;
import com.matburt.mobileorg2.OrgData.OrgDatabase;
import com.matburt.mobileorg2.OrgData.OrgFile;
import com.matburt.mobileorg2.OrgData.OrgFileParser;
import com.matburt.mobileorg2.OrgData.OrgProviderUtils;
import com.matburt.mobileorg2.R;
import com.matburt.mobileorg2.util.FileUtils;
+import com.matburt.mobileorg2.util.OrgFileNotFoundException;
-import org.eclipse.jgit.api.CheckoutResult;
+import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.errors.CanceledException;
@@ -45,7 +37,9 @@
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import java.io.BufferedReader;
@@ -147,6 +141,7 @@ public static SyncResult pull(final Context context) {
result.setState(SyncResult.State.kSuccess);
return result;
} catch(WrongRepositoryStateException e){
+ e.printStackTrace();
handleMergeConflict(git, context);
} catch (IOException
| DetachedHeadException
@@ -297,6 +292,69 @@ protected Void doInBackground(String... params) {
e.printStackTrace();
} catch (WrongRepositoryStateException e) {
e.printStackTrace();
+ handleMergeConflict(git,context);
+ } catch (ConcurrentRefUpdateException e) {
+ e.printStackTrace();
+ } catch (NoHeadException e) {
+ e.printStackTrace();
+ } catch (NoMessageException e) {
+ e.printStackTrace();
+ } catch (GitAPIException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ static public class MergeTask extends AsyncTask {
+ Context context;
+
+ public MergeTask(Context context) {
+ this.context = context;
+ }
+
+ protected Void doInBackground(String... params) {
+ Log.v("git", "merging");
+
+ File repoDir = new File(context.getFilesDir() + "/" + GIT_DIR + "/.git");
+ Git git = null;
+ try {
+ git = Git.open(repoDir);
+
+ CheckoutCommand coCmd = git.checkout();
+// Commands are part of the api module, which include git-like calls
+ coCmd.setName("master");
+ coCmd.setCreateBranch(false); // probably not needed, just to make sure
+ Ref ref = coCmd.call();
+
+ // Stage all changed files, omitting new files, and commit with one command
+ git.merge()
+ .setStrategy(MergeStrategy.OURS)
+ .include(ref)
+ .call();
+
+ git.add()
+ .addFilepattern("google.org").call();
+
+ org.eclipse.jgit.api.Status status = git.status().call();
+ System.out.println("Added: " + status.getAdded());
+ System.out.println("Changed: " + status.getChanged());
+ System.out.println("Conflicting: " + status.getConflicting());
+ System.out.println("Missing: " + status.getMissing());
+ System.out.println("Modified: " + status.getModified());
+ System.out.println("Removed: " + status.getRemoved());
+ System.out.println("Untracked: " + status.getUntracked());
+
+ AuthData authData = AuthData.getInstance(context);
+ git.push()
+ .setCredentialsProvider(new CredentialsProviderAllowHost(authData.getUser(), authData.getPassword()))
+ .call();
+ System.out.println("Committed all changes to repository at ");
+ } catch (IOException | UnmergedPathsException e) {
+ e.printStackTrace();
+ } catch (WrongRepositoryStateException e) {
+ e.printStackTrace();
+ handleMergeConflict(git,context);
} catch (ConcurrentRefUpdateException e) {
e.printStackTrace();
} catch (NoHeadException e) {
@@ -321,17 +379,17 @@ private static void handleMergeConflict(Git git, Context context){
status = git.status().call();
ContentResolver resolver = context.getContentResolver();
for(String file: status.getConflicting()){
-// OrgFile f = new OrgFile(f, resolver);
-// ContentValues values = new ContentValues();
-// values.put()
-// f.updateFile(resolver, values);
-
-
+ OrgFile f = new OrgFile(file, resolver);
+ ContentValues values = new ContentValues();
+ values.put("comment","conflict");
+ f.updateFileInDB(resolver, values);
}
} catch (GitAPIException e1) {
e1.printStackTrace();
return;
+ } catch (OrgFileNotFoundException e) {
+ e.printStackTrace();
}
diff --git a/MobileOrg/src/main/java/com/matburt/mobileorg2/util/OrgUtils.java b/MobileOrg/src/main/java/com/matburt/mobileorg2/util/OrgUtils.java
index 445da107..90702bce 100644
--- a/MobileOrg/src/main/java/com/matburt/mobileorg2/util/OrgUtils.java
+++ b/MobileOrg/src/main/java/com/matburt/mobileorg2/util/OrgUtils.java
@@ -20,36 +20,42 @@
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
public class OrgUtils {
-
+
public static String getTimestamp() {
- SimpleDateFormat sdf = new SimpleDateFormat("[yyyy-MM-dd EEE HH:mm]");
+ SimpleDateFormat sdf = new SimpleDateFormat("[yyyy-MM-dd EEE HH:mm]");
return sdf.format(new Date());
}
-
- public static void setupSpinnerWithEmpty(Spinner spinner, ArrayList data,
- String selection) {
+
+ public static void setupSpinnerWithEmpty(Spinner spinner, ArrayList data,
+ String selection) {
data.add("");
setupSpinner(spinner, data, selection);
- }
-
+ }
+
public static void setupSpinner(Spinner spinner, ArrayList data,
- String selection) {
+ String selection) {
if(!TextUtils.isEmpty(selection) && !data.contains(selection))
data.add(selection);
-
+
ArrayAdapter adapter = new ArrayAdapter(spinner.getContext(),
android.R.layout.simple_spinner_item, data);
adapter.setDropDownViewResource(R.layout.edit_spinner_layout);
@@ -60,7 +66,7 @@ public static void setupSpinner(Spinner spinner, ArrayList data,
}
spinner.setSelection(pos, true);
}
-
+
public static OrgNode getCaptureIntentContents(Intent intent) {
String subject = intent
.getStringExtra("android.intent.extra.SUBJECT");
@@ -70,7 +76,7 @@ public static OrgNode getCaptureIntentContents(Intent intent) {
subject = "[[" + text + "][" + subject + "]]";
text = "";
}
-
+
if(subject == null)
subject = "";
if(text == null)
@@ -81,59 +87,59 @@ public static OrgNode getCaptureIntentContents(Intent intent) {
node.setPayload(text);
return node;
}
-
+
public static long getNodeFromPath(String path, ContentResolver resolver) throws OrgFileNotFoundException {
String filename = path.substring("file://".length(), path.length());
-
+
// TODO Handle links to headings instead of simply stripping it out
if(filename.indexOf(":") > -1)
filename = filename.substring(0, filename.indexOf(":"));
-
+
OrgFile file = new OrgFile(filename, resolver);
return file.nodeId;
}
-
+
public static void announceSyncDone(Context context) {
Intent intent = new Intent(SynchronizerManager.SYNC_UPDATE);
intent.putExtra(SynchronizerManager.SYNC_DONE, true);
context.sendBroadcast(intent);
}
-
+
public static void announceSyncStart(Context context) {
Intent intent = new Intent(SynchronizerManager.SYNC_UPDATE);
intent.putExtra(SynchronizerManager.SYNC_START, true);
context.sendBroadcast(intent);
}
-
+
public static void announceSyncUpdateProgress(int progress, Context context) {
Intent intent = new Intent(SynchronizerManager.SYNC_UPDATE);
intent.putExtra(SynchronizerManager.SYNC_PROGRESS_UPDATE, progress);
context.sendBroadcast(intent);
}
- public static String getStringFromResource(int resource, Context context) {
- InputStream is = context.getResources().openRawResource(resource);
- BufferedReader br = new BufferedReader(new InputStreamReader(is));
- String readLine = null;
- String contents = "";
-
- try {
- // While the BufferedReader readLine is not null
- while ((readLine = br.readLine()) != null) {
- contents += readLine + "\n";
- }
-
- // Close the InputStream and BufferedReader
- is.close();
- br.close();
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- return contents;
- }
-
+ public static String getStringFromResource(int resource, Context context) {
+ InputStream is = context.getResources().openRawResource(resource);
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String readLine = null;
+ String contents = "";
+
+ try {
+ // While the BufferedReader readLine is not null
+ while ((readLine = br.readLine()) != null) {
+ contents += readLine + "\n";
+ }
+
+ // Close the InputStream and BufferedReader
+ is.close();
+ br.close();
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return contents;
+ }
+
public static String rightTrim(String str) {
int last = str.length() - 1;
int end = last;
@@ -208,7 +214,7 @@ public static String lookUpValueFromArray(Context context, int keyID, int valID,
}
return null;
}
-
+
public static boolean isWifiOnline(Context context) {
ConnectivityManager conMan = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -250,4 +256,38 @@ public int compare(Object o1, Object o2) {
return s1.toLowerCase().compareTo(s2.toLowerCase());
}
}
+
+ /**
+ * Read content of file on disk
+ * @param filename
+ * The absolute filename
+ * @return
+ */
+ static public String readAll(String filename){
+ try {
+ FileReader fileReader = new FileReader(filename);
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+ StringBuilder stringBuilder = new StringBuilder();
+
+ String currentLine;
+ while ((currentLine = bufferedReader.readLine()) != null) stringBuilder.append(currentLine + "\n");
+ return stringBuilder.toString();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ static public void writeToFile(String filename, String content) {
+ try {
+ File file = new File(filename);
+ OutputStream outputStream = new FileOutputStream(file);
+ OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+ outputStreamWriter.write(content);
+ outputStreamWriter.close();
+ }
+ catch (IOException e) {
+ Log.e("Exception", "File write failed: " + e.toString());
+ }
+ }
}
diff --git a/MobileOrg/src/main/res/layout/activity_conflict_resolver.xml b/MobileOrg/src/main/res/layout/activity_conflict_resolver.xml
new file mode 100644
index 00000000..4cad4b62
--- /dev/null
+++ b/MobileOrg/src/main/res/layout/activity_conflict_resolver.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MobileOrg/src/main/res/layout/outline_item.xml b/MobileOrg/src/main/res/layout/outline_item.xml
index 667939a0..1bb0c75f 100644
--- a/MobileOrg/src/main/res/layout/outline_item.xml
+++ b/MobileOrg/src/main/res/layout/outline_item.xml
@@ -20,24 +20,32 @@
card_view:cardCornerRadius="4dp"
android:layout_margin="5dp">
-
+
-
-
+
\ No newline at end of file
diff --git a/MobileOrg/src/main/res/values-w820dp/dimens.xml b/MobileOrg/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..63fc8164
--- /dev/null
+++ b/MobileOrg/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/MobileOrg/src/main/res/values/dimens.xml b/MobileOrg/src/main/res/values/dimens.xml
index be6feca2..a4489c29 100644
--- a/MobileOrg/src/main/res/values/dimens.xml
+++ b/MobileOrg/src/main/res/values/dimens.xml
@@ -13,4 +13,7 @@
35dip
45dip
45dip
+
+ 16dp
+ 16dp
diff --git a/MobileOrg/src/main/res/values/strings.xml b/MobileOrg/src/main/res/values/strings.xml
index 0b9855f0..0370c98e 100644
--- a/MobileOrg/src/main/res/values/strings.xml
+++ b/MobileOrg/src/main/res/values/strings.xml
@@ -33,6 +33,7 @@
Filename
Details
You have no node in this file
+ Conflict
You cannot select this item