From f40ed114618e3ff27ee5a91733487f27a897be74 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Sun, 17 Aug 2014 22:17:54 +0200
Subject: [PATCH 01/33] Fix URL Encoding

---
 .../db/AsyncDatabaseConnector.java            | 88 +++++++++++++++++--
 1 file changed, 81 insertions(+), 7 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index d8a0261..8aeef5c 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -2,6 +2,7 @@ package info.nerull7.mysqlbrowser.db;
 
 import android.os.AsyncTask;
 import android.util.Log;
+import android.widget.ArrayAdapter;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -10,8 +11,10 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLEncoder;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -54,11 +57,32 @@ public class AsyncDatabaseConnector {
         matrixReturnListener=null;
     }
 
-    private String actionUrlBuilder(String action){ // TODO Better UrlBuilder this is shit only for use
+    private String actionUrlBuilder(String action){
         String urlBuilder = url;
         urlBuilder += "?u="+login;
         urlBuilder += "&p="+password;
         urlBuilder += "&a="+action;
+
+        return urlBuilder;
+    }
+
+    private String actionUrlBuilder(String action, String argument, String value){
+        ArrayList<String> arguments = new ArrayList<String>();
+        ArrayList<String> values = new ArrayList<String>();
+        arguments.add(argument);
+        values.add(value);
+        return this.actionUrlBuilder(action, arguments, values);
+    }
+
+    private String actionUrlBuilder(String action, List<String> arguments, List<String> values){ // TODO Better UrlBuilder this is shit only for use
+        String urlBuilder = actionUrlBuilder(action);
+        for (int i = 0; i < arguments.size(); i++) {
+            try {
+                urlBuilder += "&" + arguments.get(i) + "=" + URLEncoder.encode(values.get(i), "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+        }
 //        Log.d("URLBuilder", urlBuilder);
         return urlBuilder;
     }
@@ -147,20 +171,53 @@ public class AsyncDatabaseConnector {
     }
 
     public void getTables(){
-        getList(actionUrlBuilder(ACTION_TABLE_LIST)+"&d="+database);
+        getList(actionUrlBuilder(ACTION_TABLE_LIST, "d", database));
     }
 
     public void getFields(String table){
-        getList(actionUrlBuilder(ACTION_FIELD_LIST)+"&d="+database+"&t="+table);
+        ArrayList<String> args = new ArrayList<String>();
+        ArrayList<String> values = new ArrayList<String>();
+
+        args.add("d");
+        values.add(database);
+
+        args.add("t");
+        values.add(table);
+
+        getList(actionUrlBuilder(ACTION_FIELD_LIST, args, values));
     }
 
     public void getRows(String table, int count, int page){
         int limitStart = (page-1) * count;
-        getMatrix(actionUrlBuilder(ACTION_DATA_MATRIX)+"&d="+database+"&t="+table+"&s="+limitStart+"&l="+count);
+        ArrayList<String> args = new ArrayList<String>();
+        ArrayList<String> values = new ArrayList<String>();
+
+        args.add("d");
+        values.add(database);
+
+        args.add("t");
+        values.add(table);
+
+        args.add("s");
+        values.add(String.valueOf(limitStart));
+
+        args.add("l");
+        values.add(String.valueOf(count));
+
+        getMatrix(actionUrlBuilder(ACTION_DATA_MATRIX, args, values) );
     }
 
     public void getEntriesCount(String table){
-        String urlQuery = actionUrlBuilder(ACTION_ENTRIES_COUNT)+"&d="+database+"&t="+table;
+        ArrayList<String> args = new ArrayList<String>();
+        ArrayList<String> values = new ArrayList<String>();
+
+        args.add("d");
+        values.add(database);
+
+        args.add("t");
+        values.add(table);
+
+        String urlQuery = actionUrlBuilder(ACTION_ENTRIES_COUNT, args, values);
         Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
             @Override
             public void onFinished(String data, String error) {
@@ -180,6 +237,15 @@ public class AsyncDatabaseConnector {
         JSONArray newValuesJSON = new JSONArray();
         String request;
 
+        ArrayList<String> args = new ArrayList<String>();
+        ArrayList<String> values = new ArrayList<String>();
+
+        args.add("d");
+        values.add(database);
+
+        args.add("t");
+        values.add(table);
+
         for (String aHeader : header) {
             headerJSON.put(aHeader);
         }
@@ -188,14 +254,22 @@ public class AsyncDatabaseConnector {
             newValuesJSON.put(newValue);
         }
 
+        args.add("h");
+        values.add(headerJSON.toString());
+
+        args.add("v");
+        values.add(newValuesJSON.toString());
+
         if(oldValues!=null){
             JSONArray oldValuesJSON = new JSONArray();
             for(int i=0;i<newValues.size();i++){
                 oldValuesJSON.put(oldValues.get(i));
             }
-            request = actionUrlBuilder(ACTION_UPDATE_ELEMENT)+"&d="+database+"&t="+table+"&h="+headerJSON+"&v="+newValuesJSON+"&o="+oldValuesJSON;
+            args.add("o");
+            values.add(oldValuesJSON.toString());
+            request = actionUrlBuilder(ACTION_UPDATE_ELEMENT, args, values);
         } else
-            request = actionUrlBuilder(ACTION_ADD_ELEMENT)+"&d="+database+"&t="+table+"&h="+headerJSON+"&v="+newValuesJSON;
+            request = actionUrlBuilder(ACTION_ADD_ELEMENT, args, values);
 
         Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
             @Override

From f691d83fab6edf947ce08efd915b81e63aa269a7 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Tue, 19 Aug 2014 23:06:07 +0200
Subject: [PATCH 02/33] Fix different fields height

---
 .../main/java/info/nerull7/mysqlbrowser/EntriesFragment.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
index 53f7e40..670324e 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
@@ -102,7 +102,7 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
             }
         });
 
-        layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
+        layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT);
         headerFrame.setVisibility(View.INVISIBLE);
         entriesTable.setVisibility(View.INVISIBLE);
     }

From 697c2e845a95e52b2047dceaf76b7840cf329285 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 01:30:50 +0200
Subject: [PATCH 03/33] More jobs on AsyncTask DO NOT MERGE

not finished yet.
---
 app/src/main/AndroidManifest.xml              |  3 ++
 .../mysqlbrowser/DatabaseFragment.java        |  9 +++-
 .../nerull7/mysqlbrowser/EntriesFragment.java | 34 +++++++++-----
 .../nerull7/mysqlbrowser/LoginFragment.java   | 10 ++--
 .../nerull7/mysqlbrowser/TableFragment.java   |  9 +++-
 .../db/AsyncDatabaseConnector.java            | 46 +++++++++++++++----
 6 files changed, 85 insertions(+), 26 deletions(-)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 792b2c8..39f66fe 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,4 +39,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
 </manifest>
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
index d02e088..c70f172 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
@@ -24,11 +24,12 @@ import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
  *
  * Fragment for showing list of Available Databases for user
  */
-public class DatabaseFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener {
+public class DatabaseFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
     private ListView databasesListView;
     private ListAdapter listAdapter;
     private RelativeLayout rootView;
     private ProgressBar progressBar;
+    private List<String> databases;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
@@ -39,6 +40,7 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
         progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
 
         Static.asyncDatabaseConnector.setListReturnListener(this);
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
         Static.asyncDatabaseConnector.getDatabases();
         return rootView;
     }
@@ -60,6 +62,11 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
 
     @Override
     public void onListReturn(List<String> databases) {
+        this.databases = databases;
+    }
+
+    @Override
+    public void onPostExecute() {
         if(databases!= null) {
             listAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, databases);
             databasesListView.setAdapter(listAdapter);
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
index 670324e..f46b353 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
@@ -31,7 +31,7 @@ import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
  *
  * Fragment for showing elements
  */
-public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.IntegerReturnListener, View.OnClickListener {
+public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.IntegerReturnListener, View.OnClickListener, AsyncDatabaseConnector.OnPostExecuteListener {
     private static final int HEADER_PADDING_TOP = 15;
     private static final int HEADER_PADDING_BOTTOM = 15;
     private static final int HEADER_PADDING_LEFT = 15;
@@ -57,7 +57,10 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
     private CustomScrollView fakeScrollView;
     private View dummyView;
 
+    private int onPostExecuteListenerExecuted;
+
     private Menu menu;
+    private TableRow headerRow;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -70,6 +73,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         Static.asyncDatabaseConnector.setIntegerReturnListener(this);
         Static.asyncDatabaseConnector.setListReturnListener(this);
         Static.asyncDatabaseConnector.setMatrixReturnListener(this);
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
+        onPostExecuteListenerExecuted = 0;
         Static.asyncDatabaseConnector.getFields(tableName);
         Static.asyncDatabaseConnector.getEntriesCount(tableName);
 
@@ -203,9 +208,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
                 newRow.setClickable(true);
                 newRow.setOnClickListener(this);
                 entriesTable.addView(newRow);
-
-                syncWidths();
-                fakeScroll();
             }
         } else {
             TextView errorMessage = new TextView(getActivity());
@@ -223,7 +225,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
     @Override
     public void onListReturn(List<String> fieldList) {
         // First we need header
-        TableRow headerRow;
         headerRow = new TableRow(getActivity());
         headerRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
         rowCount = fieldList.size();
@@ -236,7 +237,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
             textView.setPadding(HEADER_PADDING_LEFT, HEADER_PADDING_TOP, HEADER_PADDING_RIGHT, HEADER_PADDING_BOTTOM);
             headerRow.addView(textView);
         }
-        headerFrame.addView(headerRow);
 
         Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page);
     }
@@ -246,12 +246,15 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         pageCount = result/entriesLimit;
         if( result%entriesLimit > 0)
             pageCount++;
-
-        setHasOptionsMenu(true);
+        getActivity().runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                setHasOptionsMenu(true);
+            }
+        });
     }
 
     private void syncWidths(){ // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
-        TableRow headerRow = (TableRow) headerFrame.getChildAt(0);
         int maxWidth[]= new int[headerRow.getChildCount()];
         for(int i=0;i<headerRow.getChildCount();i++){
             TextView textView = (TextView) headerRow.getChildAt(i);
@@ -280,8 +283,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
             tmpHeader.setWidth(maxWidth[i]);
         }
 
-        headerFrame.setVisibility(View.VISIBLE);
-        entriesTable.setVisibility(View.VISIBLE);
+//        headerFrame.setVisibility(View.VISIBLE);
+//        entriesTable.setVisibility(View.VISIBLE);
     }
 
     private void fakeScroll(){
@@ -311,4 +314,13 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         intent.putStringArrayListExtra(ElementFragment.EDIT_LIST, values);
         startActivity(intent);
     }
+
+    @Override
+    public void onPostExecute() {
+        if(++onPostExecuteListenerExecuted==3){
+            headerFrame.addView(headerRow);
+            syncWidths();
+            fakeScroll();
+        }
+    }
 }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
index 73e145d..726d080 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
@@ -19,7 +19,7 @@ import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
  *
  * Fragment for login
  */
-public class LoginFragment extends Fragment implements View.OnClickListener, AsyncDatabaseConnector.BooleanReturnListener {
+public class LoginFragment extends Fragment implements View.OnClickListener, AsyncDatabaseConnector.BooleanReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
     private EditText urlTextbox;
     private EditText loginTextbox;
     private EditText passwordTextbox;
@@ -86,6 +86,7 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
         if(Static.isNetworkConnected(getActivity())) {
             asyncDatabaseConnector = new AsyncDatabaseConnector(login, password, url);
             asyncDatabaseConnector.setBooleanReturnListener(this);
+            asyncDatabaseConnector.setOnPostExecuteListener(this);
             asyncDatabaseConnector.checkLogin();
         } else {
             Static.showErrorAlert(getResources().getString(R.string.no_connection), getActivity());
@@ -105,9 +106,12 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
         else {
             Static.showErrorAlert(AsyncDatabaseConnector.errorMsg, getActivity());
         }
-        loginButton.setEnabled(true); // Now we can click button again
-        progressBar.setVisibility(View.INVISIBLE);
     }
 
 
+    @Override
+    public void onPostExecute() {
+        loginButton.setEnabled(true); // Now we can click button again
+        progressBar.setVisibility(View.INVISIBLE);
+    }
 }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java
index 8a63cd4..1007f2c 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java
@@ -22,12 +22,13 @@ import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
 /**
  * Created by nerull7 on 14.07.14.
  */
-public class TableFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener{
+public class TableFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
     private String databaseName;
     private ListView tablesList;
     private ListAdapter listAdapter;
     private RelativeLayout rootView;
     private ProgressBar progressBar;
+    private List<String> tables;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -38,6 +39,7 @@ public class TableFragment extends Fragment implements AdapterView.OnItemClickLi
         this.rootView = (RelativeLayout) rootView;
         progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
         Static.asyncDatabaseConnector.setListReturnListener(this);
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
         Static.asyncDatabaseConnector.getTables();
         return rootView;
     }
@@ -59,6 +61,11 @@ public class TableFragment extends Fragment implements AdapterView.OnItemClickLi
 
     @Override
     public void onListReturn(List<String> tables) {
+        this.tables = tables;
+    }
+
+    @Override
+    public void onPostExecute() {
         if(tables != null) {
             listAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1, tables);
             tablesList.setAdapter(listAdapter);
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 8aeef5c..0f01403 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -45,6 +45,7 @@ public class AsyncDatabaseConnector {
     private MatrixReturnListener matrixReturnListener;
 
     public static String errorMsg;
+    private OnPostExecuteListener onPostExecuteListener;
 
     public AsyncDatabaseConnector(String login, String password, String url){
         this.login = login;
@@ -99,10 +100,18 @@ public class AsyncDatabaseConnector {
                 try {
                     list = parseListFromJSON(data);
                 } catch (JSONException e) { e.printStackTrace(); }
-                if(listReturnListener!=null)
-                    listReturnListener.onListReturn(list);
+                if(listReturnListener!=null) {
+                    final List<String> finalList = list;
+//                    new Thread(new Runnable() {
+//                        @Override
+//                        public void run() {
+                            listReturnListener.onListReturn(finalList);
+//
+//                        }
+//                    }).run();
+                }
             }
-        });
+        }, onPostExecuteListener);
         downloader.execute(urlQuery);
     }
 
@@ -117,7 +126,7 @@ public class AsyncDatabaseConnector {
                 if(matrixReturnListener!=null)
                     matrixReturnListener.onMatrixReturn(list);
             }
-        });
+        }, onPostExecuteListener);
         downloader.execute(urlQuery);
     }
 
@@ -161,7 +170,7 @@ public class AsyncDatabaseConnector {
 
                 booleanReturnListener.onBooleanReturn(listenerData);
             }
-        });
+        }, onPostExecuteListener);
         downloader.execute(actionUrlBuilder(ACTION_LOGIN));
         return false;
     }
@@ -224,7 +233,7 @@ public class AsyncDatabaseConnector {
                 if(integerReturnListener!=null)
                     integerReturnListener.onIntegerReturn(Integer.parseInt(data));
             }
-        });
+        }, onPostExecuteListener);
         downloader.execute(urlQuery);
     }
 
@@ -278,7 +287,7 @@ public class AsyncDatabaseConnector {
                     stringReturnListener.onStringReturn(data);
                 }
             }
-        });
+        }, onPostExecuteListener);
         downloader.execute(request);
     }
 
@@ -302,6 +311,10 @@ public class AsyncDatabaseConnector {
         this.matrixReturnListener = matrixReturnListener;
     }
 
+    public void setOnPostExecuteListener(OnPostExecuteListener onPostExecuteListener){
+        this.onPostExecuteListener = onPostExecuteListener;
+    }
+
     public static interface BooleanReturnListener{
         public void onBooleanReturn(boolean result);
     }
@@ -322,16 +335,22 @@ public class AsyncDatabaseConnector {
         public void onMatrixReturn(List<List<String>> data);
     }
 
+    public static interface OnPostExecuteListener {
+        void onPostExecute();
+    }
+
     private static class Downloader extends AsyncTask<String, Void, String> {
         private OnFinishedListener onFinishedListener;
+        private OnPostExecuteListener onPostExecuteListener;
         private String errorString;
 
         public static final String CONNECTION_REQUEST_METHOD = "GET";
         public static final int CONNECTION_TIMEOUT = 15000;
         public static final int READ_TIMEOUT = 10000;
 
-        Downloader(OnFinishedListener onFinishedListener){
+        Downloader(OnFinishedListener onFinishedListener, OnPostExecuteListener onPostExecuteListener){
             this.onFinishedListener = onFinishedListener;
+            this.onPostExecuteListener = onPostExecuteListener;
             errorString = null;
         }
 
@@ -385,7 +404,8 @@ public class AsyncDatabaseConnector {
         @Override
         protected String doInBackground(String... strings) {
             try {
-                return httpRequest(strings[0]);
+                String data = httpRequest(strings[0]);
+                onFinishedListener.onFinished(data, errorMsg); // Can't be null cos we demand listener in constructor
             } catch (IOException e) {
                 e.printStackTrace();
             }
@@ -394,11 +414,17 @@ public class AsyncDatabaseConnector {
 
         @Override
         protected void onPostExecute(String data) {
-            onFinishedListener.onFinished(data, errorString); // Can't be null cos we demand listener in constructor
+            if (onPostExecuteListener!=null)
+                onPostExecuteListener.onPostExecute();
+        }
+
+        public void setOnPostExecuteListener(OnPostExecuteListener onPostExecuteListener) {
+            this.onPostExecuteListener = onPostExecuteListener;
         }
 
         private static interface OnFinishedListener {
             void onFinished(String data, String error);
         }
+
     }
 }

From e48b75863e1389992b673bb530adec9855c02bd7 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 11:24:55 +0200
Subject: [PATCH 04/33] Better UI

 Less actions on main thread.
---
 .../nerull7/mysqlbrowser/ElementFragment.java | 41 +++++++++++---
 .../nerull7/mysqlbrowser/EntriesFragment.java | 55 ++++++++++---------
 app/src/main/res/layout/fragment_entries.xml  | 10 ++--
 3 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index 898c6ba..65e7685 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -24,10 +24,15 @@ import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
  *
  * Fragment for editing/adding elements
  */
-public class ElementFragment extends Fragment implements AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.StringReturnListener {
+public class ElementFragment extends Fragment implements AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.StringReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
     public static final String EDIT_ELEMENT = "edit_element";
     public static final String EDIT_LIST = "edit_element_list";
 
+    private static final int POST_EXECUTE_NONE = 0;
+    private static final int POST_EXECUTE_GET_FIELDS = 1;
+    private static final int POST_EXECUTE_UPDATE_ELEMENT = 2;
+    private static final int POST_EXECUTE_ADD_ELEMENT = 3;
+
     private String tableName;
     private ElementArrayAdapter listAdapter;
 
@@ -35,6 +40,8 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
     private ListView listView;
 
     private List<String> values;
+    private String message;
+    private int postExecute;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -45,7 +52,9 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
 
         initArguments();
 
+        postExecute = POST_EXECUTE_NONE;
         Static.asyncDatabaseConnector.setListReturnListener(this);
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
         Static.asyncDatabaseConnector.getFields(tableName);
 
         return rootView;
@@ -84,12 +93,8 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
     @Override
     public void onListReturn(List<String> fields) {
         listAdapter = new ElementArrayAdapter(getActivity(), R.layout.list_item_element_simple, fields, values);
-        listView.setAdapter(listAdapter);
-//        databasesListView.setAdapter(listAdapter);
-//        databasesListView.setOnItemClickListener(this);
-        progressBar.setVisibility(View.INVISIBLE);
+        postExecute = POST_EXECUTE_GET_FIELDS;
 
-        setHasOptionsMenu(true);
     }
 
     private List<String> getNewValues(){
@@ -104,8 +109,30 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
 
     @Override
     public void onStringReturn(String data) {
+        message = data;
+        postExecute = POST_EXECUTE_ADD_ELEMENT;
+    }
+
+    @Override
+    public void onPostExecute() {
+        switch (postExecute){
+            case POST_EXECUTE_GET_FIELDS:
+                listView.setAdapter(listAdapter);
+                progressBar.setVisibility(View.INVISIBLE);
+                setHasOptionsMenu(true);
+                break;
+            case POST_EXECUTE_ADD_ELEMENT:
+            case POST_EXECUTE_UPDATE_ELEMENT:
+                showInfo(message);
+                break;
+        }
+        // Clean after execute
+        postExecute = POST_EXECUTE_NONE;
+    }
+
+    private void showInfo(String info){
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
-        builder.setMessage(data);
+        builder.setMessage(info);
         builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialogInterface, int i) {
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
index f46b353..f0a6583 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
@@ -61,6 +61,7 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
 
     private Menu menu;
     private TableRow headerRow;
+    private int[] maxWidth;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -91,12 +92,12 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
 
     private void initViewItems(View rootView){
         headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame);
-        entriesTable = (TableLayout) rootView.findViewById(R.id.entriesTable);
         entriesScrollView = (ScrollView) rootView.findViewById(R.id.entriesScrollView);
         fakeScrollView = (CustomScrollView) rootView.findViewById(R.id.fakeScroll);
         progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
         dummyView = rootView.findViewById(R.id.dummyView);
         horizontalScrollView = (HorizontalScrollView) rootView.findViewById(R.id.horizontalScrollView);
+        entriesTable = new TableLayout(getActivity());
 
         fakeScrollView.setOnTouchEventListener(new CustomScrollView.OnTouchEventListener() {
             @Override
@@ -108,8 +109,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         });
 
         layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT);
-        headerFrame.setVisibility(View.INVISIBLE);
-        entriesTable.setVisibility(View.INVISIBLE);
     }
 
     @Override
@@ -146,7 +145,9 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
 
     private void loadAnotherPage(){
         changeMenus(page);
-        entriesTable.removeAllViews(); // clean table
+        entriesScrollView.removeAllViews(); // clean table
+        entriesTable = new TableLayout(getActivity());
+        onPostExecuteListenerExecuted--;
 
         setLoading(true);
         Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page); // get new entries
@@ -208,18 +209,12 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
                 newRow.setClickable(true);
                 newRow.setOnClickListener(this);
                 entriesTable.addView(newRow);
+                syncWidthsFirstStage();
             }
         } else {
-            TextView errorMessage = new TextView(getActivity());
-            errorMessage.setText(R.string.error_no_entries);
-            errorMessage.setTypeface(null, Typeface.ITALIC);
-            errorMessage.setClickable(false);
-            entriesScrollView.removeView(entriesTable);
-            headerFrame.setVisibility(View.VISIBLE);
-            entriesScrollView.addView(errorMessage);
+            entriesTable = null;
         }
 
-        setLoading(false);
     }
 
     @Override
@@ -254,25 +249,27 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         });
     }
 
-    private void syncWidths(){ // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
-        int maxWidth[]= new int[headerRow.getChildCount()];
-        for(int i=0;i<headerRow.getChildCount();i++){
+    private void syncWidthsFirstStage() { // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
+        maxWidth = new int[headerRow.getChildCount()];
+        for (int i = 0; i < headerRow.getChildCount(); i++) {
             TextView textView = (TextView) headerRow.getChildAt(i);
             textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
             maxWidth[i] = textView.getMeasuredWidth();
         }
 
-        for(int i=0;i<entriesTable.getChildCount();i++){
+        for (int i = 0; i < entriesTable.getChildCount(); i++) {
             TableRow tableRow = (TableRow) entriesTable.getChildAt(i);
-            for(int j=0;j<tableRow.getChildCount();j++){
+            for (int j = 0; j < tableRow.getChildCount(); j++) {
                 TextView textView = (TextView) tableRow.getChildAt(j);
                 textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
                 int width = textView.getMeasuredWidth();
-                if(width>maxWidth[j])
-                    maxWidth[j]=width;
+                if (width > maxWidth[j])
+                    maxWidth[j] = width;
             }
         }
+    }
 
+    private void syncWidthsSecondStage() {
         for(int i=0;i<headerRow.getChildCount();i++){
             TableRow entriesRow = (TableRow) entriesTable.getChildAt(0);
 
@@ -282,9 +279,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
             tmpEntries.setWidth(maxWidth[i]);
             tmpHeader.setWidth(maxWidth[i]);
         }
-
-//        headerFrame.setVisibility(View.VISIBLE);
-//        entriesTable.setVisibility(View.VISIBLE);
     }
 
     private void fakeScroll(){
@@ -318,9 +312,20 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
     @Override
     public void onPostExecute() {
         if(++onPostExecuteListenerExecuted==3){
-            headerFrame.addView(headerRow);
-            syncWidths();
-            fakeScroll();
+            if(entriesTable!=null) {
+                syncWidthsSecondStage();
+                fakeScroll();
+                entriesScrollView.addView(entriesTable);
+            } else {
+                TextView errorMessage = new TextView(getActivity());
+                errorMessage.setText(R.string.error_no_entries);
+                errorMessage.setTypeface(null, Typeface.ITALIC);
+                errorMessage.setClickable(false);
+                entriesScrollView.addView(errorMessage);
+            }
+            if(headerFrame.getChildCount()==0) // You can have only one child
+                headerFrame.addView(headerRow);
+            setLoading(false);
         }
     }
 }
diff --git a/app/src/main/res/layout/fragment_entries.xml b/app/src/main/res/layout/fragment_entries.xml
index 3ed823a..55f3cb8 100644
--- a/app/src/main/res/layout/fragment_entries.xml
+++ b/app/src/main/res/layout/fragment_entries.xml
@@ -26,11 +26,11 @@
                 android:id="@+id/entriesScrollView"
                 android:layout_below="@+id/headerFrame"
                 android:scrollbars="none">
-                <TableLayout
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:id="@+id/entriesTable">
-                </TableLayout>
+                <!--<TableLayout-->
+                    <!--android:layout_width="wrap_content"-->
+                    <!--android:layout_height="wrap_content"-->
+                    <!--android:id="@+id/entriesTable">-->
+                <!--</TableLayout>-->
             </ScrollView>
         </RelativeLayout>
     </HorizontalScrollView>

From 475a7b4c6184e6fcee99a10b894ddb22407d5dfe Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 11:25:55 +0200
Subject: [PATCH 05/33] Fix for info box

---
 app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index 65e7685..bfa7c97 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -147,6 +147,7 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
         });*/
         builder.setTitle(R.string.status);
         builder.setIcon(R.drawable.ic_action_warning); //TODO Change Icon
+        builder.setCancelable(false); // There is no exit
         builder.create();
         builder.show();
     }

From 87c276dfc4dd613e4de899134ccd4745704ddea1 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 11:37:02 +0200
Subject: [PATCH 06/33] Reload table after changes

---
 .../nerull7/mysqlbrowser/EntriesFragment.java | 26 ++++++++++++++++---
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
index f0a6583..e9f09f6 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
@@ -63,6 +63,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
     private TableRow headerRow;
     private int[] maxWidth;
 
+    private boolean isFirstCreate;
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
@@ -70,11 +72,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
 
         initArguments();
         initViewItems(rootView);
+        initListeners();
 
-        Static.asyncDatabaseConnector.setIntegerReturnListener(this);
-        Static.asyncDatabaseConnector.setListReturnListener(this);
-        Static.asyncDatabaseConnector.setMatrixReturnListener(this);
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
         onPostExecuteListenerExecuted = 0;
         Static.asyncDatabaseConnector.getFields(tableName);
         Static.asyncDatabaseConnector.getEntriesCount(tableName);
@@ -86,6 +85,7 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         databaseName = getArguments().getString(Static.DATABASE_NAME_ARG);
         tableName = getArguments().getString(Static.TABLE_NAME_ARG);
         page = 1;
+        isFirstCreate = true;
 
         entriesLimit = PreferenceManager.getDefaultSharedPreferences(getActivity()).getInt(SettingsFragment.ENTRIES_PAGE_LIMIT, SettingsFragment.ENTRIES_PAGE_LIMIT_DEF);
     }
@@ -111,6 +111,13 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT);
     }
 
+    private void initListeners(){
+        Static.asyncDatabaseConnector.setIntegerReturnListener(this);
+        Static.asyncDatabaseConnector.setListReturnListener(this);
+        Static.asyncDatabaseConnector.setMatrixReturnListener(this);
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
+    }
+
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.entries_activity_actions, menu);
@@ -309,6 +316,17 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         startActivity(intent);
     }
 
+    @Override
+    public void onResume() {
+        super.onResume();
+        if(!isFirstCreate) {
+            initListeners(); // Could be overwritten
+            loadAnotherPage(); // This reloads entries
+        } else {
+            isFirstCreate = false;
+        }
+    }
+
     @Override
     public void onPostExecute() {
         if(++onPostExecuteListenerExecuted==3){

From 298fab290a3473cd6933b8052252af7742414a74 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 11:38:53 +0200
Subject: [PATCH 07/33] Don't need URL log now.

---
 .../info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 0f01403..01f8911 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -359,7 +359,7 @@ public class AsyncDatabaseConnector {
             InputStream inputStream = null;
             String response;
 
-            Log.d("URL REQUEST", urlRequest);
+//            Log.d("URL REQUEST", urlRequest);
 
             HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();  // TODO Handling no connection
             urlConnection.setReadTimeout(READ_TIMEOUT);

From 2b661013bdd3ee3ce96b67cd4e4adf8918d4d167 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 11:39:39 +0200
Subject: [PATCH 08/33] Remove unused commented code.

---
 .../nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java  | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 01f8911..f02a60a 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -101,14 +101,7 @@ public class AsyncDatabaseConnector {
                     list = parseListFromJSON(data);
                 } catch (JSONException e) { e.printStackTrace(); }
                 if(listReturnListener!=null) {
-                    final List<String> finalList = list;
-//                    new Thread(new Runnable() {
-//                        @Override
-//                        public void run() {
-                            listReturnListener.onListReturn(finalList);
-//
-//                        }
-//                    }).run();
+                    listReturnListener.onListReturn(list);
                 }
             }
         }, onPostExecuteListener);

From ba87ba1291c6bf04bce06e1ff52b4a183c54f561 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 11:47:01 +0200
Subject: [PATCH 09/33] Set more generic Type

---
 .../java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
index 5f4c427..9004c95 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
@@ -40,7 +40,7 @@ public class ElementArrayAdapter extends ArrayAdapter<String> {
         TextView textView = (TextView) rowView.findViewById(R.id.textFieldName);
         textView.setText(fields.get(position));
         if(values != null){
-            EditText textFieldName = (EditText) rowView.findViewById(R.id.editFieldValue);
+            TextView textFieldName = (TextView) rowView.findViewById(R.id.editFieldValue);
             textFieldName.setText(values.get(position));
         }
 

From 555a428af40ea08a5880efbbf89a37651be87c1d Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 12:16:05 +0200
Subject: [PATCH 10/33] Fix not showing scroll

---
 .../java/info/nerull7/mysqlbrowser/EntriesFragment.java  | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
index e9f09f6..9bf12ef 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
@@ -294,7 +294,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         dummyView.setMinimumHeight(height);
 
         RelativeLayout.LayoutParams fakeScrollLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
-        fakeScrollLayout.setMargins(0,headerFrame.getHeight(),0,0);
+        headerFrame.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        fakeScrollLayout.setMargins(0,headerFrame.getMeasuredHeight(),0,0);
 
         fakeScrollView.setLayoutParams(fakeScrollLayout);
     }
@@ -330,10 +331,12 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
     @Override
     public void onPostExecute() {
         if(++onPostExecuteListenerExecuted==3){
+            if(headerFrame.getChildCount()==0) // You can have only one child
+                headerFrame.addView(headerRow);
             if(entriesTable!=null) {
                 syncWidthsSecondStage();
-                fakeScroll();
                 entriesScrollView.addView(entriesTable);
+                fakeScroll();
             } else {
                 TextView errorMessage = new TextView(getActivity());
                 errorMessage.setText(R.string.error_no_entries);
@@ -341,8 +344,6 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
                 errorMessage.setClickable(false);
                 entriesScrollView.addView(errorMessage);
             }
-            if(headerFrame.getChildCount()==0) // You can have only one child
-                headerFrame.addView(headerRow);
             setLoading(false);
         }
     }

From 7bcbe46d91954d9ab37e549eff4dcfb76e9c1707 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:07:12 +0200
Subject: [PATCH 11/33] Added remove element

---
 .../nerull7/mysqlbrowser/ElementFragment.java |  10 +++-
 .../nerull7/mysqlbrowser/LoginFragment.java   |  12 +++--
 .../db/AsyncDatabaseConnector.java            |  44 +++++++++++++++++-
 .../res/drawable-hdpi/ic_action_delete.png    | Bin 0 -> 764 bytes
 .../res/drawable-mdpi/ic_action_delete.png    | Bin 0 -> 507 bytes
 .../res/drawable-xhdpi/ic_action_delete.png   | Bin 0 -> 990 bytes
 .../res/drawable-xxhdpi/ic_action_delete.png  | Bin 0 -> 1721 bytes
 app/src/main/res/menu/element.xml             |   5 ++
 app/src/main/res/values/strings.xml           |   2 +
 9 files changed, 66 insertions(+), 7 deletions(-)
 create mode 100644 app/src/main/res/drawable-hdpi/ic_action_delete.png
 create mode 100644 app/src/main/res/drawable-mdpi/ic_action_delete.png
 create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_delete.png
 create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_delete.png

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index bfa7c97..42eba73 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -62,15 +62,18 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        List<String> fields = listAdapter.getFieldArray();
         if(item.getItemId() == R.id.action_save ){
-            List<String> fields = listAdapter.getFieldArray();
-
             Static.asyncDatabaseConnector.setStringReturnListener(this);
             if(getArguments().getBoolean(EDIT_ELEMENT))
                 Static.asyncDatabaseConnector.updateElement(tableName, fields, values, getNewValues());
             else
                 Static.asyncDatabaseConnector.addNewElement(tableName, fields, getNewValues());
             return true;
+        } else if(item.getItemId() == R.id.action_remove) {
+            Static.asyncDatabaseConnector.setStringReturnListener(this);
+            Static.asyncDatabaseConnector.removeElement(tableName, fields, values);
+            return true;
         } else {
             return super.onOptionsItemSelected(item);
         }
@@ -87,6 +90,9 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
     @Override
     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
         inflater.inflate(R.menu.element, menu);
+        if(!getArguments().getBoolean(EDIT_ELEMENT)) {
+            menu.findItem(R.id.action_remove).setVisible(false);
+        }
         super.onCreateOptionsMenu(menu, inflater);
     }
 
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
index 726d080..b3b048c 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
@@ -28,6 +28,8 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
 
     AsyncDatabaseConnector asyncDatabaseConnector;
 
+    private boolean result;
+
     public LoginFragment(){}
 
     @Override
@@ -97,6 +99,12 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
 
     @Override
     public void onBooleanReturn(boolean result) {
+        this.result = result;
+    }
+
+
+    @Override
+    public void onPostExecute() {
         if(result) {
             Static.asyncDatabaseConnector = asyncDatabaseConnector;
             Intent intent = new Intent(getActivity(), ListActivity.class);
@@ -106,11 +114,7 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
         else {
             Static.showErrorAlert(AsyncDatabaseConnector.errorMsg, getActivity());
         }
-    }
 
-
-    @Override
-    public void onPostExecute() {
         loginButton.setEnabled(true); // Now we can click button again
         progressBar.setVisibility(View.INVISIBLE);
     }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index f02a60a..8a8872f 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -31,6 +31,7 @@ public class AsyncDatabaseConnector {
     public static final String ACTION_DATA_MATRIX = "getrows";
     public static final String ACTION_ADD_ELEMENT = "addelement";
     public static final String ACTION_UPDATE_ELEMENT = "updateelement";
+    public static final String ACTION_REMOVE_ELEMENT = "removeelement";
 
     private String login;
     private String password;
@@ -206,7 +207,7 @@ public class AsyncDatabaseConnector {
         args.add("l");
         values.add(String.valueOf(count));
 
-        getMatrix(actionUrlBuilder(ACTION_DATA_MATRIX, args, values) );
+        getMatrix(actionUrlBuilder(ACTION_DATA_MATRIX, args, values));
     }
 
     public void getEntriesCount(String table){
@@ -284,6 +285,47 @@ public class AsyncDatabaseConnector {
         downloader.execute(request);
     }
 
+    public void removeElement(String table, List<String> header, List<String> values) {
+        JSONArray headerJSON = new JSONArray();
+        JSONArray valuesJSON = new JSONArray();
+        String request;
+
+        ArrayList<String> args = new ArrayList<String>();
+        ArrayList<String> argValues = new ArrayList<String>();
+
+        args.add("d");
+        argValues.add(database);
+
+        args.add("t");
+        argValues.add(table);
+
+        for (String aHeader : header) {
+            headerJSON.put(aHeader);
+        }
+
+        for (String value : values) {
+            valuesJSON.put(value);
+        }
+
+        args.add("h");
+        argValues.add(headerJSON.toString());
+
+        args.add("v");
+        argValues.add(valuesJSON.toString());
+
+        request = actionUrlBuilder(ACTION_REMOVE_ELEMENT, args, argValues);
+
+        Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
+            @Override
+            public void onFinished(String data, String error) {
+                if(stringReturnListener!=null){
+                    stringReturnListener.onStringReturn(data);
+                }
+            }
+        }, onPostExecuteListener);
+        downloader.execute(request);
+    }
+
     public void setBooleanReturnListener(BooleanReturnListener booleanReturnListener){
         this.booleanReturnListener = booleanReturnListener;
     }
diff --git a/app/src/main/res/drawable-hdpi/ic_action_delete.png b/app/src/main/res/drawable-hdpi/ic_action_delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..49e4513d88cf182c6efcb7c684f85fc1456f70be
GIT binary patch
literal 764
zcmV<Y0t5YtP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0008RNkl<ZXhZE;
zOGs8h6!y2$O;+GeH`1;^30f3^8x0ava3SQAwk=(@(S>bl*V3){$e=|~f`YmUL>ECQ
z<SyFiPVBX@hx&bR@6R;dJ7;G82Ojal$JKw%nRC9Gb7s!WEz~G~3d;SjIVT{@U^+m@
zm73{t%|I<2Y)R0JcO%dM)FqDp!utoX59|V85*(FEtW*M5;lN$sHgGM_nXi!l0Biu?
z0(Fbxu>>xohx@=C;6kkNMDH)&o4^Y2GqkT50=HnK2e=YyOpyPM_IJR?kbXl5FwVPy
z_7DRRvhSg@2zcd(FM&(wa0Iv!;ZTgq4wPnr-;%Nq0gn8mDmtI~OcK-5O!yG!twPx3
z4K%~)t!ow}0!-K;X&NisKJQ9w7XdDnV?eoAn^3-7on8Q$ORS4PAC&G1*0_eh25tha
zfu3zc{u9s-NPEdTWZq=;pGSZ@>=U75IzN**!9*VpAVKHnk_09BQ4d?sAoJgjok!pS
zggb>1eT8<G0_k%Re+&R^g5DO|7l1#897~ahg5E0Hmu;CW0vt__zEs<oqiB*Cbj$>G
zURuuk&fWp^o+q<b<dH?-I$9qKqmed;I21$Jc4G=Zd^Uf~BEZmL2>Cu)Az_D;kBpDK
zB?zra1ej1UD@vM_b~y3>*s!rlaTd97I75hQf0NH}STcFxL@~24<LtQd#ASL9jocHQ
z1jf<I(^Slp6)I*wzAIIpZJz3$x(F~QCV~1G?-QM@WMz}@YU46}h{g$^c*eGqSUmx<
zR~<qmpgxJ!FQXlpg|2`k_SvL-WPD6|ZDi_8iPKul@gj^R^*^^2XR@4TEUG`ykc8?Z
zB?+iM)RTnjYn60eR(-LRR*|Z&7D+<&<!%~Es;}40Iz{aV4wHoHPfR8ewIBKH(pT+g
uR;h+p^PyWJQn7aF3r)ogm#bs-1Wo|IXw)%-dy;hk0000<MNUMnLSTZmt6qBm

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-mdpi/ic_action_delete.png b/app/src/main/res/drawable-mdpi/ic_action_delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..2706550e95d428313d6e9d999f57faf06cc66b33
GIT binary patch
literal 507
zcmV<X0R;YuP)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80005PNkl<ZSVzT|
zPbft}6vp3UiC$r^WGSyCYirgd%ErRmlbw~FSYu(MNUT{~ONuO&>`}tfpYMBSYMjp8
zxpS#=>&tWI%sIa~^Y7kz&G@Ms=dV=-=mB^?)a3^7j=zu4Ywmz@0GMzb8g|LGT!grV
zE*wyjrwjl`IR%YE9m$A44xi8!bPBOL(I*8kgr0Lycge)k?G1)Q=q}d32%w2hvruQn
z<i6VnejGv9TAUaFN51$E$wP=etr8jl=Y07OWsen%)3GJjga$AJr!ghU3v3V2NMcHE
z&^`b)6u(Q@jzhZy;8t6K<Z5T~UFZp#jsP+)6P!SO(2@ed-LVOAyS5(*FbUg)Le5bg
zKwqwp2H}%?pLzId)jEg$EC#TO23A3PWP%W)s7=P==r=R~9<OVW<ld|$VjIg|R2><1
z9ftO?9Zta@{%<7!*eoGv%SlfEZRlPC@Qhz50U#lKoT9}k!|ubtJL6Xc%mK`&z<d#M
zN=&yQ0n87gqN8{RfX`5wqqx^?X?Y(ck78EA^fDrV`E^VP(-#tdYMH*0c?i>&QV(JJ
xS{_~^W*;Wn1!?kWR`RCKb4z_0<wdLD{S5+*j3Jmsy~O|k002ovPDHLkV1m;y-kJaa

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xhdpi/ic_action_delete.png b/app/src/main/res/drawable-xhdpi/ic_action_delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..1487306f124b1ba77501573e78888f41bb0b96fe
GIT binary patch
literal 990
zcmV<410np0P)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF000A}Nkl<ZcwX&W
zIjl}W6n-y=HH09d&{!g&laNqYDoa5kp|C3`G!zsHg+f6=qaeYv6(kZ0OJylYNOTmo
zMj?U_Vhs}CC;!OJm^*XM+<V`<FXv72<^S)!=gge*&6)Mi?d~$3x{dqaH9){X1Q=(a
zH=DpHa6Ji_2#f|s0)spJ|HAJV;1lo$cny5+jk;-)fI)CzIxq{E3XE4e^bYbbfXBcy
z;I~p=B;Eu8tl7E1JYby2inP#sh};JrbRs3KA(W_-06M-9SO5$Wmai5235C1Bow|sq
zi-6fMXeBU4>rtlsN9bJv9%btPQ>#kAaOAWGU_0-N#QxzT@GZCSDg;bGq3eLjxrNuH
z_X_!(2j1r7mrKAD6t)!@kyB^`I$x3JN#Lb6?;HZ?{1$+nUYio<5vQ~yXbE80?`ToY
z`xU@QII3w58UoniZEr!FPemR3gkylHW7H6^37Pg)Z=Z77f6me2v_wft0LS@_k_=lU
za|X5~=Lr%5*xBs_w3D0<&>343Avt+*vUCJs=UAE~1T2U4BBdjow_gR;12dGmzW7tz
zI0vi%xW3S&+Yr81g#gz6UO+RqzXkd0okF?X-CThLI^P3uxy-Z-Sgc@xYlj0sX%wU)
zfQ7M8X=2S^@`Q)tdP4>Ybp9;x!^>|qt~HUs%3!4gQ;Yzv=XV3rB`w?OVc>h9ByA-4
zHDAnf7%p}J(*A`@=|ezpKOsiIOek@>t4T4#rIAop^Rz=tq_h15{yYge5+gtxYA*jO
z4%9(l$j?yI{3{nDU=N;ax3P*O^x(pEUPYtIBB2U#sVL?4+CfbOa07E+D%ZqwjYCb<
ze9^@HxcG0QwJZXrL3mq50;n!=jB=sgzDk=9nSLBMpZgEW2$&DSRW%UcNQgN|8BJ5k
zHS01I?@0+*3c)40B?a_ikq{~-x3`a(d=n3END0Ut0b&Nk`h=pMbhy;kPjDnCYXWPL
z`y6cv0{K)VG*R=;tcUn>K^g((2{7LT%y)w3he7ibA@fsVjuxgDLnI(~B+x8^{9#$L
zcF5Ud%vuhc-w-jsCC2bHy(vlp%x{a61k*1@TojmoHAWIlzZ`XAwdvR6B*FXv36fy?
zh>U9rrVmLKNicg%&XHjHprj+g^ikR3Qr7HY=^_cHkIVZ+nEYVE-`(MU0ykILJgR&$
z!?S*TtJ`lrnemBm*XBN&DkGv*_fyB@T4ih##tab91grfiPxBG*2MGKYP<l%#F#rGn
M07*qoM6N<$f;$_*VgLXD

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_delete.png b/app/src/main/res/drawable-xxhdpi/ic_action_delete.png
new file mode 100644
index 0000000000000000000000000000000000000000..251f91da422b503afb01693827c75e4be9d4915e
GIT binary patch
literal 1721
zcmV;q21fabP)<h;3K|Lk000e1NJLTq003YB003YJ1^@s6;+S_h000JnNkl<ZcwX&Y
zU8q$>6!r%d&7{z@2uw665i~^YArKA1kiZAEB>F)?1+}M0NCgoLLGh_XR8T4jD}4w;
z6rn`$!HTFLR7kl#h?<5{YFMOwpPpUY!`Wxg&ssC*p1TG<^xiu&Yu5T^*8I=z-_Jr;
z3-r$_-Guiu0y0+uBftpAY=O+;tpykXnJti6d~a?6Ec<|l{chvmJDF`6B)-!LcmP^G
z28;nl0S^Jg0sek4FtDNZKlt}A;0ACVxCUGSE&&%BzYj8ycA`!rU?>!x2uuLR0gnh7
z;4<>*0nPv?fj@=vjn1YM2w)kW0wy<%&)TgS*h)ykPrzv)tLw^1z#u693@`(DLet`H
z@;-;ZeFOXe{GFo=IS3d6MV|#`0rcmc5ZG@V1x^6BQWhvR0aKvd3&7}<N_xop6>*OM
zKYFBzikgam2T{s7z;qy$%uvIyPxux%4EzzAiEFwP#-NX%3k-8DRENa7iE<nS*hi=Z
zO#(PZr@NWm3u=9pf!P|qZn!1RHN=A!0j%u{fl1;e&XeKK5c@g6Rv{WR2zVGJTncdJ
z+D(Bo>s`QANu{I-pwZt1xOC8s;Ubj!2p}0EL6QL0{3Ts%{KDWQVUJWxkRpISe^nQ{
zovK>S7VrTO-6u#8z|qcYK(}<buC9e0^IjlobR<E*izvkNuBGm>cwa%ELoqtV62M8;
zd>}TT7#(t^<vig45Ik9nF&vi{-UfQx3|E>k_5)jipk<2~0v13hTY!aoEnt6$Awmh@
zs^+VLu7^!Iv@9WdGmWH7=Jg5Sy^0#5G}rUr0;HCdxkL3Sz}3>nL#^qV?mXgiweuA~
zY6p%>+3y2h`w1Zg%!H7aJQc2rPUC+JoCUby&RMiJ2{itP05|T(1Fs8`@Fns(=3^UQ
z0=SL%E+Da!^;^RboLLruoAS#PNucp}0_9ElM;pYC^f6pTT<)xG0-U!ueF@-(3RgK}
z18e>cpltjiPpy_vuKCU7Cke}iS^`&1xuN3}d<bCN6+r9;dfDw%6;hgncE&HtAmxsF
zkl}W~>9mCp0Z$`SF1E!47K#g5ryMeoa!0M)PL+7-xES!UORKzgJL>2q=w)O&&B1VW
zQCw=Hlsif(tE~5T_~ElUL-6meOtUtw2Bd~;KD9E`9r+kvs<jn1r<>gj)Skd|C15Ht
zTjav1M;uK9r69OY)qRNYeO)A10yy&F2uM2kkl@-9H1Z75n<F8Ph}s5M0_c9U_IM?0
ztB>)e-A=Qic_4U;1OfE>>+3R#{JVtVB#Dev=fC6|@IUqkmBFP2Jc-ntooWXk5}Msn
zOj=F7IP3l;mVoDw!92}Umhuj%#Y|qT?bH=h+wC;V{{p`_9!mg?PZClEpV~}=GSm+D
z5XZF>m(-KSCkd6o#RYMNGWCYL4+$;?%VB($iyQZBolykvxXD--ErsLwxTAKWQ@fpV
zS<c~yZLtJs4ngZUi){(HYJQ;?&ku1%9NYrvqSgW<>MW)B_fQgY8=ofm9e59@Tp6wF
z19<3a9U!#^6v~sYJId*H$~tlmuo0*{yk!K0RtdLs(FB+aax-*QtY{a+jI9$6Cn35M
zrf3_6h7%w%47G_^H~}IPF<XiVCqQH=!WQGg2@qL~v*qY;0z{UhZ9^uU0FezDihl=?
zdb_7t9iLfl-SUFZvW50+S!_#^2D43h|5hNnDR0M8{0R^}mSP99{0I;~m__k+G|`;|
z@uP_pZHIH+2~atlYsb^w2<SmHmE-9YZx=M`Nl?3>LD9UTv<8saA+sw=Fl611SS!Bm
zl3sNyP`{){(RNL>H37-4sZzXM)V`mDq!+ad(e_lq|0E=Ts(_;Hv5tELWP7ZG!tJ@5
zjL+2+4bUEJs-GKF#t0dPHfLr}mSrY@;yE!}325CTi%?M|DbM@x)N|YGM=p{jT0kMk
zo~?ATcvBon0+=;hz#9M`zv#x$(GRzlTf)*VbVt47>EeO}_6eM*rM}vv)#`Y{jc>w5
z`~2ntO1q$P{`P#mLv_$3pb&2#aA-qB3IZtJK4DTpLMj3Z@%9lP<zc9U*Sou)V4tyS
zSSoc3C=<l(O@7FY`^@89m{W+;gFJbHtxtW(t<^}(K4qv-yF#+Gk9mezO)-sq&Q{U5
zv01bKvJX1PTCuOE&p8U}>$bnEzY&nR8W;gaKxPYM7H=)U2*_-K%;NtATo1f(VxgWZ
P00000NkvXXu0mjfj7Sv9

literal 0
HcmV?d00001

diff --git a/app/src/main/res/menu/element.xml b/app/src/main/res/menu/element.xml
index 8f2cd4b..f3262ad 100644
--- a/app/src/main/res/menu/element.xml
+++ b/app/src/main/res/menu/element.xml
@@ -7,4 +7,9 @@
         android:showAsAction="always"
         android:icon="@drawable/ic_action_save"/>
 
+    <item android:id="@+id/action_remove"
+        android:title="@string/action_remove"
+        android:showAsAction="always"
+        android:icon="@drawable/ic_action_delete"/>
+
 </menu>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index db2bbf2..5cea4e6 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -39,5 +39,7 @@
     <string name="warning">Warning</string>
     <string name="status">Status</string>
     <string name="back">Back</string>
+    <string name="action_remove">Remove</string>
+
 
 </resources>

From 93c8d65cfa76e759d8943c07ac3ce9bcdf29afb8 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:20:12 +0200
Subject: [PATCH 12/33] Added warning before remove entry

---
 .../nerull7/mysqlbrowser/ElementFragment.java | 65 ++++++++++++++-----
 app/src/main/res/values/strings.xml           |  2 +
 2 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index 42eba73..a26c459 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -60,23 +60,57 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
         return rootView;
     }
 
+    private void actionSave(){
+        List<String> fields = listAdapter.getFieldArray();
+        Static.asyncDatabaseConnector.setStringReturnListener(this);
+        if(getArguments().getBoolean(EDIT_ELEMENT))
+            Static.asyncDatabaseConnector.updateElement(tableName, fields, values, getNewValues());
+        else
+            Static.asyncDatabaseConnector.addNewElement(tableName, fields, getNewValues());
+    }
+
+    private void actionRemove(){
+        final List<String> fields = listAdapter.getFieldArray();
+        Static.asyncDatabaseConnector.setStringReturnListener(this);
+
+        final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setMessage(R.string.error_remove);
+        builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialogInterface, int i) {
+                Static.asyncDatabaseConnector.removeElement(tableName, fields, values);
+//                getActivity().finish();
+            }
+        });
+        builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
+            @Override
+            public void onClick(DialogInterface dialogInterface, int i) {
+                // Nothing to do just get back
+            }
+        });
+        builder.setTitle(R.string.warning);
+        builder.setIcon(R.drawable.ic_action_warning);
+        builder.setCancelable(false); // There is no exit
+        builder.create();
+        builder.show();
+
+
+
+    }
+
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
-        List<String> fields = listAdapter.getFieldArray();
-        if(item.getItemId() == R.id.action_save ){
-            Static.asyncDatabaseConnector.setStringReturnListener(this);
-            if(getArguments().getBoolean(EDIT_ELEMENT))
-                Static.asyncDatabaseConnector.updateElement(tableName, fields, values, getNewValues());
-            else
-                Static.asyncDatabaseConnector.addNewElement(tableName, fields, getNewValues());
-            return true;
-        } else if(item.getItemId() == R.id.action_remove) {
-            Static.asyncDatabaseConnector.setStringReturnListener(this);
-            Static.asyncDatabaseConnector.removeElement(tableName, fields, values);
-            return true;
-        } else {
-            return super.onOptionsItemSelected(item);
+        switch (item.getItemId()){
+            case R.id.action_save:
+                actionSave();
+                break;
+            case R.id.action_remove:
+                actionRemove();
+                break;
+            default:
+                return super.onOptionsItemSelected(item);
         }
+        return true;
     }
 
     private void initArguments() {
@@ -152,9 +186,10 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
             }
         });*/
         builder.setTitle(R.string.status);
-        builder.setIcon(R.drawable.ic_action_warning); //TODO Change Icon
+        builder.setIcon(R.drawable.ic_action_warning);
         builder.setCancelable(false); // There is no exit
         builder.create();
         builder.show();
     }
+
 }
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5cea4e6..2700a04 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -40,6 +40,8 @@
     <string name="status">Status</string>
     <string name="back">Back</string>
     <string name="action_remove">Remove</string>
+    <string name="error_remove">This entry will be removed from database. This action <b>CAN NOT</b> be reversed! Would you like to continue?</string>
+    <string name="no">No</string>
 
 
 </resources>

From 9bebe4407c696a00c062784a8880d7120066d80e Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:26:29 +0200
Subject: [PATCH 13/33] Some String cleanup

---
 app/src/main/res/values/strings.xml | 55 ++++++++++++++++-------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 2700a04..5bbac4d 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,47 +1,52 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-
     <string name="app_name">Mysql Browser</string>
+
     <string name="action_settings">Settings</string>
+    <string name="action_add">Add new</string>
+    <string name="action_remove">Remove</string>
+    <string name="action_previous">Previous</string>
+    <string name="action_next">Next</string>
+
+    <string name="title_activity_main">MainActivity</string>
+    <string name="title_activity_entries">EntriesActivity</string>
+    <string name="title_activity_setting">Settings</string>
+    <string name="title_activity_element">ElementActivity</string>
+    <string name="title_activity_list">ListActivity</string>
+
     <string name="login">Log in</string>
     <string name="password">Password</string>
     <string name="username">Username</string>
     <string name="hint_url">URL ex: https://example.com/c.php</string>
-    <string name="title_activity_main">MainActivity</string>
-    <string name="hello_world">Hello world!</string>
-    <string name="login_error">Wrong login/password</string>
+
+    <string name="yes">Yes</string>
+    <string name="no">No</string>
     <string name="ok">OK</string>
+    <string name="cancel">Cancel</string>
+    <string name="action_save">Save</string>
+    <string name="set">Set</string>
+    <string name="back">Back</string>
+
+    <string name="status">Status</string>
+    <string name="warning">Warning</string>
     <string name="error">Error</string>
-    <string name="title_activity_entries">EntriesActivity</string>
+
+    <string name="login_error">Wrong login/password</string>
+
     <string name="general_category">General</string>
     <string name="entries_limit">Entries per page limit</string>
     <string name="entries_summary">%s entries per page</string> <!-- <xliff:g id="count"></xliff:g> -->
-    <string name="title_activity_setting">Settings</string>
-    <string name="cancel">Cancel</string>
-    <string name="set">Set</string>
-    <string name="pref_entries_per_page">Set number of entries per page</string>
+
     <string name="error_no_tables">No tables in this database</string>
     <string name="error_no_entries">No entries in this table</string>
     <string name="error_no_databases">No available databases</string>
-    <string name="action_previous">Previous</string>
-    <string name="action_next">Next</string>
+    <string name="error_no_save">Your data will NOT be saved! Would you like to continue?</string>
+    <string name="error_remove">This entry will be removed from database. This action <b>CAN NOT</b> be reversed! Would you like to continue?</string>
+
+    <string name="pref_entries_per_page">Set number of entries per page</string>
     <string name="login_settings">Login credentials</string>
     <string name="save_credentials">Save credentials</string>
     <string name="connector_url">Connector URL</string>
     <string name="no_connection">No Internet Connection</string>
-    <string name="action_add">Add new</string>
-    <string name="title_activity_element">ElementActivity</string>
-    <string name="action_save">Save</string>
-    <string name="title_fragment_database">Available Databases</string>
-    <string name="title_activity_list">ListActivity</string>
-    <string name="error_no_save">Your data will NOT be saved! Would you like to continue?</string>
-    <string name="yes">Yes</string>
-    <string name="warning">Warning</string>
-    <string name="status">Status</string>
-    <string name="back">Back</string>
-    <string name="action_remove">Remove</string>
-    <string name="error_remove">This entry will be removed from database. This action <b>CAN NOT</b> be reversed! Would you like to continue?</string>
-    <string name="no">No</string>
-
 
 </resources>

From 2dd63650de756ba62150b5017b4cd1b49c65262f Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:31:44 +0200
Subject: [PATCH 14/33] Some Bolding

---
 app/src/main/res/values/strings.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 5bbac4d..b3a32f1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -40,7 +40,7 @@
     <string name="error_no_tables">No tables in this database</string>
     <string name="error_no_entries">No entries in this table</string>
     <string name="error_no_databases">No available databases</string>
-    <string name="error_no_save">Your data will NOT be saved! Would you like to continue?</string>
+    <string name="error_no_save">Your data will <b>NOT</b> be saved! Would you like to continue?</string>
     <string name="error_remove">This entry will be removed from database. This action <b>CAN NOT</b> be reversed! Would you like to continue?</string>
 
     <string name="pref_entries_per_page">Set number of entries per page</string>

From 23e1078c7d7135d1b18521b20c92e1bed34ca94b Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:35:58 +0200
Subject: [PATCH 15/33] Turns out we need it

 Re added title_fragment_database string.
---
 app/src/main/res/values/strings.xml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b3a32f1..d7b1d0e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -13,6 +13,7 @@
     <string name="title_activity_setting">Settings</string>
     <string name="title_activity_element">ElementActivity</string>
     <string name="title_activity_list">ListActivity</string>
+    <string name="title_fragment_database">Available Databases</string>
 
     <string name="login">Log in</string>
     <string name="password">Password</string>

From dfb3374d59653b8d8f96074d9457488d129bf49b Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:38:50 +0200
Subject: [PATCH 16/33] =?UTF-8?q?Polskie=20t=C5=82umaczenie?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/src/main/res/values-pl/strings.xml | 47 ++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 app/src/main/res/values-pl/strings.xml

diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000..35ba264
--- /dev/null
+++ b/app/src/main/res/values-pl/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">PrzeglÄ…darka Mysql</string>
+
+    <string name="action_settings">Ustawienia</string>
+    <string name="action_add">Dodaj nowy</string>
+    <string name="action_remove">Usuń</string>
+    <string name="action_previous">Poprzedni</string>
+    <string name="action_next">Następny</string>
+
+    <string name="title_fragment_database">Dostępne bazy</string>
+
+    <string name="login">Zaloguj</string>
+    <string name="password">Hasło</string>
+    <string name="username">Użytkownik</string>
+
+    <string name="yes">Tak</string>
+    <string name="no">Nie</string>
+    <string name="ok">OK</string>
+    <string name="cancel">Anuluj</string>
+    <string name="action_save">Zapisz</string>
+    <string name="set">Ustaw</string>
+    <string name="back">Cofnij</string>
+
+    <string name="status">Info</string>
+    <string name="warning">Ostrzeżenie</string>
+    <string name="error">Błąd</string>
+
+    <string name="login_error">Zły login/hasło</string>
+
+    <string name="general_category">Ogólne</string>
+    <string name="entries_limit">Limit wpisów na stronę</string>
+    <string name="entries_summary">%s na stronÄ™</string> <!-- <xliff:g id="count"></xliff:g> -->
+
+    <string name="error_no_tables">Brak tabel w tej bazie</string>
+    <string name="error_no_entries">Brak wpisów w tej bazie</string>
+    <string name="error_no_databases">Brak dostępnych baz</string>
+    <string name="error_no_save">Twoje dane <b>NIE</b> zostaną zapisane! Czy chciałbyś kontynuować?</string>
+    <string name="error_remove">Ten wpis zostanie usunięty z bazy. Tej akcji <b>NIE MOŻNA</b> cofnąć! Czy chciałbyś kontynuować?</string>
+
+    <string name="pref_entries_per_page">Ustaw limit wpisów na stronę</string>
+    <string name="login_settings">Poświadczenia logowania</string>
+    <string name="save_credentials">Zapamiętaj poświadczenia</string>
+    <string name="connector_url">URL Wtyczki php</string>
+    <string name="no_connection">Brak połączenia internetowego</string>
+
+</resources>

From 5d635e4408cd71c4589dae91753410a1b9320aa6 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 15:52:45 +0200
Subject: [PATCH 17/33] Showing connection error DO NOT MERGE

 FIXME
---
 .../mysqlbrowser/db/AsyncDatabaseConnector.java      | 12 +++++++++++-
 app/src/main/res/values/strings.xml                  |  1 +
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 8a8872f..3aceda8 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -12,12 +12,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
+import java.net.ConnectException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.util.ArrayList;
 import java.util.List;
 
+import info.nerull7.mysqlbrowser.R;
+
 /**
  * Created by nerull7 on 07.07.14.
  * Database connector using Async calls
@@ -400,7 +403,14 @@ public class AsyncDatabaseConnector {
             urlConnection.setReadTimeout(READ_TIMEOUT);
             urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
             urlConnection.setRequestMethod(CONNECTION_REQUEST_METHOD);
-            urlConnection.connect();
+            try {
+                urlConnection.connect();
+            } catch (ConnectException e) {
+//                errorMsg = e.getMessage();
+                if (e.getCause().equals(CONNECTION_REQUEST_METHOD)) {
+                    errorMsg == R.string.error_connection_timeout; // FIXME
+                }
+            }
 
             if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                 try {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d7b1d0e..c1647e7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -49,5 +49,6 @@
     <string name="save_credentials">Save credentials</string>
     <string name="connector_url">Connector URL</string>
     <string name="no_connection">No Internet Connection</string>
+    <string name="error_connection_timeout">Connection timeout</string>
 
 </resources>

From f223b58e21bd86cd9deeda160977440525edf37c Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 20:14:04 +0200
Subject: [PATCH 18/33] Add missing image

---
 .../main/res/drawable-hdpi/ic_action_save.png    | Bin 0 -> 575 bytes
 .../main/res/drawable-mdpi/ic_action_save.png    | Bin 0 -> 387 bytes
 .../main/res/drawable-xhdpi/ic_action_save.png   | Bin 0 -> 807 bytes
 .../main/res/drawable-xxhdpi/ic_action_save.png  | Bin 0 -> 1274 bytes
 4 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 app/src/main/res/drawable-hdpi/ic_action_save.png
 create mode 100644 app/src/main/res/drawable-mdpi/ic_action_save.png
 create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_save.png
 create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_save.png

diff --git a/app/src/main/res/drawable-hdpi/ic_action_save.png b/app/src/main/res/drawable-hdpi/ic_action_save.png
new file mode 100644
index 0000000000000000000000000000000000000000..107c11e10943aadbcb217dcbfb14e593c546090c
GIT binary patch
literal 575
zcmV-F0>J%=P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm00068Nkl<ZXhZE;
zxk>~<5Zzrtgblqvz(ny23=Q-z+|Wcp13}P8MKDm%#Blu!6*bcz5Ka65?@;i-;}z_{
zF!uCR_2mq9LoqP(s`|aE>N$GqwTh2=#rfBwfWNL_tU%c-FbIOvun}0dXR;@Ve=MCt
z*Fr>o7S@yoHN=0z?^G&6CtwD_#tg~WxE;dzj2l2FU_H||U)-QfTtkCnx06o5R%!ww
zzXp3}lH<TOG$3|6Nd&B7!VeBJCMKPrJeR_DD!Tv@rfsJx2++1u6$B*hwWR8^D1f<O
zRWQyXPW%1u3RooCnX6R=oUyP76a`o$&xvcSfRi*@1c?<eNnY{|p?mk|#tl}1H!!+@
zUBVtZ>;`ZghfTmtzpaA^xCg;D>^Uc`y*S^3(f77=co*;rMtiWw0%rZVJ_qX&D)26V
zb`*}7q^5wIWMUJTcLCd&>5fTi2)IQiHkg2A%=F15)dk!p6B`9^6SV{2EfYKp+yWCD
ztOAu^#B>|og*_Eywh!0m%Xk|l-t-J;caAC@^bBah=qMfDZ=(qzs>C_$Iwgb%kHY9x
zLizwRUIW?9U1`P$Pn%LSZ2tt&p6rT>KpD5!RXne7@<1ve^bd}_3cujOK8#)ze~qHj
zhWy2pB}Z*@1EU>kC3zRUX|gVy`V>{b>0~~FMFBptDv22@Ajy^w><<lKaWTN=iY@>E
N002ovPDHLkV1jPw_B#Lo

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-mdpi/ic_action_save.png b/app/src/main/res/drawable-mdpi/ic_action_save.png
new file mode 100644
index 0000000000000000000000000000000000000000..0235a4bc83af005a013905c5933184d4da8e4aa3
GIT binary patch
literal 387
zcmV-}0et?6P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80003>Nkl<ZSVv=I
z7+}CS!1gnYIsjV;@BpJF6o}P;n3;ko`T^8C2Z$fxGXt9g5`h{tDX<t>D?vwKb3i-P
z=O2OeLoytqho%RwBd|H33u?e6AiabP2f*|b6%zDv0LU>|LxP?TfH|TLIcVtZ0Fd2f
zL&gDQq(7px5FG+UnMQ`9Q3ni<5cms>`*T2i51Iy)fwUo!l^4Y!@Dpg!EFgZ2mH=ge
z{4^kDCy+2HcEBc}1xIjLVgnTSqqPH?ffjtmVF@o#yq4AuC<j{bABQENqP>&W4(J71
z@Dhh55<u}HT07tj(1KMsEC~aOo6y<;AoKSF@opgg1GS6=NV@{DBLT}n(gbq>tVu@5
ztZzUCuqK;4kj+I%15h4RepDi>qjjSc-A&hl0`mzufLhIRWP3n9zXimrf%pp{2M`gG
h)KfCrH5>2{0039UNg=?aI*kAT002ovPDHLkV1hFxkPH9-

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xhdpi/ic_action_save.png b/app/src/main/res/drawable-xhdpi/ic_action_save.png
new file mode 100644
index 0000000000000000000000000000000000000000..16927204caae70368849ffce621fce712d86756c
GIT binary patch
literal 807
zcmV+?1K9kDP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0008+Nkl<ZcwX&V
zJ4hZu5LTig@j<N8L>ocud^BkSV#;WdMo_S}u(7bv!a`G6Xd##sDbfjo0V_dUO|Xy@
zzB*AvP#Y`7CmPXjzytZ+yPJLd+}zzR4Eo>A%+B}iw|lQGEy;N+%{l%OPk>iI&KdAi
zAm;+`i=fUFsDoPCU=6UhFr8S}LOVplU$7h7#9R<f=%@!)X4|2|_&wyBu_b{+0F8XV
zFz^A7)=J<I(2L%h9gdvqR8~sh5HN;{D_mFYIG?c+I0Q^67Q8haJ8%plEFG;qoMxm1
z4gr&j-sf;^ol}(qA65ThX|<J*H3EnjEhS`;03v~{gsc+4Rzj8u2$b+6Y8}ct0fc?X
z6A;0GR{-NWou>N$6&ybWim?VTgd@hKC<+jRj!}pwz)yi9Tm~7+6XW8ifS&?>3WPIY
zdMhkuf-?&7Yk<Tx;6I8wf}K4T_YQw+Va53HB1!?50J#j?fSnhNOf`PD!al<)8Pevu
zh#_DH75|1^#8h5|^WCsUF2Wc;5d<8g$e*xVCaBl&qt9_4nEp|2i4#Dezr#*6!Mun6
z0F216X^9i?57o~bBIrWgN5j}4EO7$pJN~XA2-=I#XBaDnfN!XTR)3R5SA$WLz-KXu
zD<HA}1~{E>gQ|3i6EK3R?ifH-F6B5lZWt?O3QVICx(u2$x;vyRflW(X0ZXWU#Sj7A
z6@D>{6{CPtR5AtA-O=?1F@vz0v=cz}ufi5IfqaGkC(Rg@d*V|dC~6V^{9yuWhhGQN
zH_lBA0aWNFjED#xgA0qN$Kp;{OB^bV^VS5YHc4sp|HAbiNA{oW`TKx+93y*Wle{4I
z0l$Z%@^M~?jUj>bZE|54uW*9u4{aO*q;Hgr!ncK!v$h0C-YOe~jb6LaI|$k^Wu*WL
zmbh6u4m|B;+>TpMI8z|VA!)n33KuPS*D!kY{u?*)K>{5D;>b+pc~3wphs|NpUI7lt
lOl2ysfK(2f!=iJqfJX!{kwN&_59<H`002ovPDHLkV1fhCTwnkI

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_save.png b/app/src/main/res/drawable-xxhdpi/ic_action_save.png
new file mode 100644
index 0000000000000000000000000000000000000000..42bf5966dc034829cc3a357a071573164cd22ff7
GIT binary patch
literal 1274
zcmV<W1O@wvP)<h;3K|Lk000e1NJLTq003YB003YJ1^@s6;+S_h000ERNkl<ZcwX(D
zIfxWN6oz*_5RX7mOcWhO@CZyi5ky5J4-_>p6cevpF;P|!(Zt9D1HsHd#oI*jL_8A%
z4-g#`6HzemKs^5+reV?D?pM|Ix~6Mh!((QdSMOE*U)SrNp6=T2F599i&>c0qCGRo-
zk#_<EU;rX35IMcg00R(Nfyn7?1{i?I3PetCGr#~uRv>bEn*j*`XkZL8VUuAaVFM$N
zsciZ?2ynh^5NZ1|Ghh&stb)yk4Ui_RiQgsk^JW!&^#wrj*TZI1(a8uoek13VDj@g*
zSc}fhjUY_bDb>r74*=Hu%?XyB{@|*XBOd^rviD~|RLhYMfF0=BsH$s08{|_dM?L`d
z6`X4R!smb5K(PM0z!M1HEqFQd0dOFv_Z0si?2GRRD`>a7M2_I)C^Ued7~I}A2avY|
zN!bJ|M+QJD`Tu@F%8>!^2N0wj832C(S<6!8$N-cFzzE*u$N+=^;9ZUkKo|ht<;Vbp
z1;A+AT|ycF7qw)*2B1Kv5MRXdQWyXO(B9XAYzD|mshXDoP?J^`*Z|0MQu9h0fSPJG
z3LNz;s75-eb=3f<Nh=F%0AxC;c^LpTX=Q;8fJ`SfF9V<^tt_wskm;o6WdPKql?65c
zGM&`C41k)nvcLvFrjweN0Z@}x7T5sDbW-y&0BX|80(T4mK7;VRrO6Py`rP3mlhn;C
zX#nq_#WUC|*az6RmNrB2IvO?!HVrn`O|zihNdkBei7vyQ!+0BD-o|H^r^1%O#srmC
z7Az?MeB$OB>^h9^T{b?kzZkXzR^`+C$pB!DKLvZ}qIw^`e3E}1tg2%~G63#Dv@<2e
z&zi5nn|Xm^6@^IxKog@p2IDhlAvQi4xd}EQM6iMwwFkh`a~$>}uvk+NZ({|esP+Kf
zK%_&k(9at47_bdCJ}}sS!_^+Z1&rvnl1K{>ccoJ7ENtxo9L7j^4A9sb2)b1xaIcuP
z2e1c&`K%<;2*ll`6g!z2z{Nm9*Z)i$9tZXtfP4iEK*1iOeRpvW@@p;jF&weWEY=~J
zJheXt9Kk4GOGfJ9GZAgJc(ikAQhNXwG1^-$BX;mz2;b!n{ywg?2f%CnM}0;vXv4Mc
z_?v;|R(k+E13CeF8d#<2h_@kd%)Y|a9smdRwlxcW1QKj;tM-oz6fZAK5&$^B8!-L~
z7GmSCV~aur62wRb087z1*j>S(^IYcRLoTswKgf6p$=`puhVxaJYdK=sSqkHsPnBz1
zCo=<j^Wr6Ho}M;^5F7AY0n@(p+*fy!1dt7scSrE-h+ot`!oIdX7=~9aCd)5cJllzJ
zH$>J)bpS;Rw+eUCAa2>65>?*ykk@hcXQ#`^d=5;Vx^%HbSI$bOtF1l&I&JZ8iSU`v
zeY`pC(!d7*4{)8de7#gpp0V)~N>kc^em(%$jyF2ZaY@txz7H@)-bm)O`2tA&Uzj+F
z2<IoTlQ8G|n0x`SgM_deHVane7adn|H2qn29>LD~h+n1z^&V6Mf28zptcrl~RPz(;
zCG0V*S=1o!^D;A_OkQi-QosO2-W3dh0f?+X<n%TJ3_xTBBB!?*U;rX35IMcg00R(N
kfyn7?1{i?I3Peu-7sTY{VYt|_;s5{u07*qoM6N<$f`dpaivR!s

literal 0
HcmV?d00001


From ba8b96c22ed0f269a89bf602bafc2bd24880601e Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 20 Aug 2014 23:38:44 +0200
Subject: [PATCH 19/33] Revert "Showing connection error DO NOT MERGE"

It doesn't work right now. Work moved into error branch.

This reverts commit 5d635e4408cd71c4589dae91753410a1b9320aa6.
---
 .../mysqlbrowser/db/AsyncDatabaseConnector.java      | 12 +-----------
 app/src/main/res/values/strings.xml                  |  1 -
 2 files changed, 1 insertion(+), 12 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 3aceda8..8a8872f 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -12,15 +12,12 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
-import java.net.ConnectException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.util.ArrayList;
 import java.util.List;
 
-import info.nerull7.mysqlbrowser.R;
-
 /**
  * Created by nerull7 on 07.07.14.
  * Database connector using Async calls
@@ -403,14 +400,7 @@ public class AsyncDatabaseConnector {
             urlConnection.setReadTimeout(READ_TIMEOUT);
             urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
             urlConnection.setRequestMethod(CONNECTION_REQUEST_METHOD);
-            try {
-                urlConnection.connect();
-            } catch (ConnectException e) {
-//                errorMsg = e.getMessage();
-                if (e.getCause().equals(CONNECTION_REQUEST_METHOD)) {
-                    errorMsg == R.string.error_connection_timeout; // FIXME
-                }
-            }
+            urlConnection.connect();
 
             if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                 try {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index c1647e7..d7b1d0e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -49,6 +49,5 @@
     <string name="save_credentials">Save credentials</string>
     <string name="connector_url">Connector URL</string>
     <string name="no_connection">No Internet Connection</string>
-    <string name="error_connection_timeout">Connection timeout</string>
 
 </resources>

From d478b474fb3e1a143d9ad25ddd3464b42a0a8c54 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Thu, 21 Aug 2014 15:17:36 +0200
Subject: [PATCH 20/33] Connection error handling

---
 .../nerull7/mysqlbrowser/LoginFragment.java   |  2 +-
 .../db/AsyncDatabaseConnector.java            | 81 +++++++++++++------
 app/src/main/res/values-pl/strings.xml        |  3 +
 app/src/main/res/values/strings.xml           |  4 +
 4 files changed, 66 insertions(+), 24 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
index b3b048c..d0a1eee 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
@@ -86,7 +86,7 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
         url = urlTextbox.getText().toString();
 
         if(Static.isNetworkConnected(getActivity())) {
-            asyncDatabaseConnector = new AsyncDatabaseConnector(login, password, url);
+            asyncDatabaseConnector = new AsyncDatabaseConnector(login, password, url, getActivity().getResources());
             asyncDatabaseConnector.setBooleanReturnListener(this);
             asyncDatabaseConnector.setOnPostExecuteListener(this);
             asyncDatabaseConnector.checkLogin();
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 8a8872f..5c0bac3 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -1,5 +1,6 @@
 package info.nerull7.mysqlbrowser.db;
 
+import android.content.res.Resources;
 import android.os.AsyncTask;
 import android.util.Log;
 import android.widget.ArrayAdapter;
@@ -12,12 +13,17 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
+import java.net.ConnectException;
 import java.net.HttpURLConnection;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
 import java.net.URL;
 import java.net.URLEncoder;
 import java.util.ArrayList;
 import java.util.List;
 
+import info.nerull7.mysqlbrowser.R;
+
 /**
  * Created by nerull7 on 07.07.14.
  * Database connector using Async calls
@@ -39,6 +45,8 @@ public class AsyncDatabaseConnector {
 
     private String database;
 
+    private final Resources resources;
+
     private BooleanReturnListener booleanReturnListener;
     private IntegerReturnListener integerReturnListener;
     private StringReturnListener stringReturnListener;
@@ -48,10 +56,11 @@ public class AsyncDatabaseConnector {
     public static String errorMsg;
     private OnPostExecuteListener onPostExecuteListener;
 
-    public AsyncDatabaseConnector(String login, String password, String url){
+    public AsyncDatabaseConnector(String login, String password, String url, Resources resources){
         this.login = login;
         this.password = password;
         this.url = url;
+        this.resources = resources;
 
         booleanReturnListener=null;
         stringReturnListener=null;
@@ -104,8 +113,9 @@ public class AsyncDatabaseConnector {
                 if(listReturnListener!=null) {
                     listReturnListener.onListReturn(list);
                 }
+                errorMsg = error;
             }
-        }, onPostExecuteListener);
+        }, onPostExecuteListener, resources);
         downloader.execute(urlQuery);
     }
 
@@ -119,8 +129,9 @@ public class AsyncDatabaseConnector {
                 } catch (JSONException e) { e.printStackTrace(); }
                 if(matrixReturnListener!=null)
                     matrixReturnListener.onMatrixReturn(list);
+                errorMsg = error;
             }
-        }, onPostExecuteListener);
+        }, onPostExecuteListener, resources);
         downloader.execute(urlQuery);
     }
 
@@ -161,10 +172,9 @@ public class AsyncDatabaseConnector {
                     errorMsg = data;
                     listenerData = false;
                 }
-
                 booleanReturnListener.onBooleanReturn(listenerData);
             }
-        }, onPostExecuteListener);
+        }, onPostExecuteListener, resources);
         downloader.execute(actionUrlBuilder(ACTION_LOGIN));
         return false;
     }
@@ -226,8 +236,9 @@ public class AsyncDatabaseConnector {
             public void onFinished(String data, String error) {
                 if(integerReturnListener!=null)
                     integerReturnListener.onIntegerReturn(Integer.parseInt(data));
+                errorMsg = error;
             }
-        }, onPostExecuteListener);
+        }, onPostExecuteListener, resources);
         downloader.execute(urlQuery);
     }
 
@@ -280,8 +291,9 @@ public class AsyncDatabaseConnector {
                 if(stringReturnListener!=null){
                     stringReturnListener.onStringReturn(data);
                 }
+                errorMsg = error;
             }
-        }, onPostExecuteListener);
+        }, onPostExecuteListener, resources);
         downloader.execute(request);
     }
 
@@ -321,8 +333,9 @@ public class AsyncDatabaseConnector {
                 if(stringReturnListener!=null){
                     stringReturnListener.onStringReturn(data);
                 }
+                errorMsg = error;
             }
-        }, onPostExecuteListener);
+        }, onPostExecuteListener, resources);
         downloader.execute(request);
     }
 
@@ -378,14 +391,16 @@ public class AsyncDatabaseConnector {
         private OnFinishedListener onFinishedListener;
         private OnPostExecuteListener onPostExecuteListener;
         private String errorString;
+        private Resources resources;
 
         public static final String CONNECTION_REQUEST_METHOD = "GET";
         public static final int CONNECTION_TIMEOUT = 15000;
         public static final int READ_TIMEOUT = 10000;
 
-        Downloader(OnFinishedListener onFinishedListener, OnPostExecuteListener onPostExecuteListener){
+        Downloader(OnFinishedListener onFinishedListener, OnPostExecuteListener onPostExecuteListener, Resources resources){
             this.onFinishedListener = onFinishedListener;
             this.onPostExecuteListener = onPostExecuteListener;
+            this.resources = resources;
             errorString = null;
         }
 
@@ -400,22 +415,42 @@ public class AsyncDatabaseConnector {
             urlConnection.setReadTimeout(READ_TIMEOUT);
             urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
             urlConnection.setRequestMethod(CONNECTION_REQUEST_METHOD);
-            urlConnection.connect();
 
-            if(urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
-                try {
-                    inputStream = urlConnection.getInputStream();
-                    response = readStream(inputStream);
-                } finally {
-                    if(inputStream!=null)
-                        inputStream.close();
-                    urlConnection.disconnect();
+            try {
+                urlConnection.connect();
+
+                if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                    try {
+                        inputStream = urlConnection.getInputStream();
+                        response = readStream(inputStream);
+                    } finally {
+                        if (inputStream != null)
+                            inputStream.close();
+                        urlConnection.disconnect();
+                    }
+                    return response;
+                } else {
+                    errorString = "ERROR " + urlConnection.getResponseCode() + ": " + urlConnection.getResponseMessage();
                 }
-                return response;
+            } catch (Exception e) {
+                parseException(e);
             }
-            else {
-                errorString = "ERROR "+urlConnection.getResponseCode()+": "+urlConnection.getResponseMessage();
-                return null;
+            return null;
+        }
+
+        private void parseException(Exception e){
+            if(e instanceof SocketException){
+                if(e.getMessage().contains("ECONNREFUSED")) {
+                    errorString = resources.getString(R.string.error_connection_refused);
+                } else if(e.getMessage().contains("EHOSTUNREACH")) {
+                    errorString = resources.getString(R.string.error_connection_unreachable);
+                } else {
+                    errorString = "Exception: " + e.getClass();
+                }
+            } else if (e instanceof  SocketTimeoutException){
+                errorString = resources.getString(R.string.error_connection_timeout);
+            } else {
+                errorString = "Exception: " + e.getClass();
             }
         }
 
@@ -440,7 +475,7 @@ public class AsyncDatabaseConnector {
         protected String doInBackground(String... strings) {
             try {
                 String data = httpRequest(strings[0]);
-                onFinishedListener.onFinished(data, errorMsg); // Can't be null cos we demand listener in constructor
+                onFinishedListener.onFinished(data, errorString); // Can't be null cos we demand listener in constructor
             } catch (IOException e) {
                 e.printStackTrace();
             }
diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml
index 35ba264..44d7f9e 100644
--- a/app/src/main/res/values-pl/strings.xml
+++ b/app/src/main/res/values-pl/strings.xml
@@ -37,6 +37,9 @@
     <string name="error_no_databases">Brak dostępnych baz</string>
     <string name="error_no_save">Twoje dane <b>NIE</b> zostaną zapisane! Czy chciałbyś kontynuować?</string>
     <string name="error_remove">Ten wpis zostanie usunięty z bazy. Tej akcji <b>NIE MOŻNA</b> cofnąć! Czy chciałbyś kontynuować?</string>
+    <string name="error_connection_timeout">Przekroczono czas połączenia</string>
+    <string name="error_connection_reset">Połączenie zostało zrestartowane</string>
+    <string name="error_connection_unreachable">No route to host</string>
 
     <string name="pref_entries_per_page">Ustaw limit wpisów na stronę</string>
     <string name="login_settings">Poświadczenia logowania</string>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d7b1d0e..ec32bc1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -43,6 +43,10 @@
     <string name="error_no_databases">No available databases</string>
     <string name="error_no_save">Your data will <b>NOT</b> be saved! Would you like to continue?</string>
     <string name="error_remove">This entry will be removed from database. This action <b>CAN NOT</b> be reversed! Would you like to continue?</string>
+    <string name="error_connection_timeout">Connection timeout</string>
+    <string name="error_connection_reset">Connection reset by peer</string>
+    <string name="error_connection_refused">Connection refused</string>
+    <string name="error_connection_unreachable">No route to host</string>
 
     <string name="pref_entries_per_page">Set number of entries per page</string>
     <string name="login_settings">Login credentials</string>

From fae910fc8c3df91de1a8fa0773a16193b85740e1 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Tue, 16 Sep 2014 11:25:54 +0200
Subject: [PATCH 21/33] Time to POST it

Moved away from sending data in GET request and now using POST requests.
---
 .../db/AsyncDatabaseConnector.java            | 68 ++++++++++++-------
 1 file changed, 42 insertions(+), 26 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 5c0bac3..277dbb7 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -2,8 +2,6 @@ package info.nerull7.mysqlbrowser.db;
 
 import android.content.res.Resources;
 import android.os.AsyncTask;
-import android.util.Log;
-import android.widget.ArrayAdapter;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -12,8 +10,9 @@ import java.io.BufferedReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.UnsupportedEncodingException;
-import java.net.ConnectException;
 import java.net.HttpURLConnection;
 import java.net.SocketException;
 import java.net.SocketTimeoutException;
@@ -68,16 +67,17 @@ public class AsyncDatabaseConnector {
         matrixReturnListener=null;
     }
 
-    private String actionUrlBuilder(String action){
-        String urlBuilder = url;
-        urlBuilder += "?u="+login;
-        urlBuilder += "&p="+password;
-        urlBuilder += "&a="+action;
+    private Request requestBuilder(String action){
+        Request request = new Request(url);
+        String urlData   = "u="+login
+                         + "&p="+password
+                         + "&a="+action;
+        request.data = urlData;
 
-        return urlBuilder;
+        return request;
     }
 
-    private String actionUrlBuilder(String action, String argument, String value){
+    private Request actionUrlBuilder(String action, String argument, String value){
         ArrayList<String> arguments = new ArrayList<String>();
         ArrayList<String> values = new ArrayList<String>();
         arguments.add(argument);
@@ -85,11 +85,11 @@ public class AsyncDatabaseConnector {
         return this.actionUrlBuilder(action, arguments, values);
     }
 
-    private String actionUrlBuilder(String action, List<String> arguments, List<String> values){ // TODO Better UrlBuilder this is shit only for use
-        String urlBuilder = actionUrlBuilder(action);
+    private Request actionUrlBuilder(String action, List<String> arguments, List<String> values){ // TODO Better UrlBuilder this is shit only for use
+        Request urlBuilder = requestBuilder(action);
         for (int i = 0; i < arguments.size(); i++) {
             try {
-                urlBuilder += "&" + arguments.get(i) + "=" + URLEncoder.encode(values.get(i), "UTF-8");
+                urlBuilder.data += "&" + arguments.get(i) + "=" + URLEncoder.encode(values.get(i), "UTF-8");
             } catch (UnsupportedEncodingException e) {
                 e.printStackTrace();
             }
@@ -102,7 +102,7 @@ public class AsyncDatabaseConnector {
         this.database = database;
     }
 
-    private void getList(String urlQuery){
+    private void getList(Request urlQuery){
         Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
             @Override
             public void onFinished(String data, String error) {
@@ -119,7 +119,7 @@ public class AsyncDatabaseConnector {
         downloader.execute(urlQuery);
     }
 
-    private void getMatrix(String urlQuery){
+    private void getMatrix(Request urlQuery){
         Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
             @Override
             public void onFinished(String data, String error) {
@@ -175,12 +175,12 @@ public class AsyncDatabaseConnector {
                 booleanReturnListener.onBooleanReturn(listenerData);
             }
         }, onPostExecuteListener, resources);
-        downloader.execute(actionUrlBuilder(ACTION_LOGIN));
+        downloader.execute(requestBuilder(ACTION_LOGIN));
         return false;
     }
 
     public void getDatabases(){
-        getList(actionUrlBuilder(ACTION_DATABASE_LIST));
+        getList(requestBuilder(ACTION_DATABASE_LIST));
     }
 
     public void getTables(){
@@ -230,7 +230,7 @@ public class AsyncDatabaseConnector {
         args.add("t");
         values.add(table);
 
-        String urlQuery = actionUrlBuilder(ACTION_ENTRIES_COUNT, args, values);
+        Request urlQuery = actionUrlBuilder(ACTION_ENTRIES_COUNT, args, values);
         Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
             @Override
             public void onFinished(String data, String error) {
@@ -249,7 +249,7 @@ public class AsyncDatabaseConnector {
     public void updateElement(String table, List<String> header, List<String> oldValues, List<String> newValues){
         JSONArray headerJSON = new JSONArray();
         JSONArray newValuesJSON = new JSONArray();
-        String request;
+        Request request;
 
         ArrayList<String> args = new ArrayList<String>();
         ArrayList<String> values = new ArrayList<String>();
@@ -300,7 +300,7 @@ public class AsyncDatabaseConnector {
     public void removeElement(String table, List<String> header, List<String> values) {
         JSONArray headerJSON = new JSONArray();
         JSONArray valuesJSON = new JSONArray();
-        String request;
+        Request request;
 
         ArrayList<String> args = new ArrayList<String>();
         ArrayList<String> argValues = new ArrayList<String>();
@@ -387,13 +387,13 @@ public class AsyncDatabaseConnector {
         void onPostExecute();
     }
 
-    private static class Downloader extends AsyncTask<String, Void, String> {
+    private static class Downloader extends AsyncTask<Request, Void, String> {
         private OnFinishedListener onFinishedListener;
         private OnPostExecuteListener onPostExecuteListener;
         private String errorString;
         private Resources resources;
 
-        public static final String CONNECTION_REQUEST_METHOD = "GET";
+        public static final String CONNECTION_REQUEST_METHOD = "POST";
         public static final int CONNECTION_TIMEOUT = 15000;
         public static final int READ_TIMEOUT = 10000;
 
@@ -404,8 +404,8 @@ public class AsyncDatabaseConnector {
             errorString = null;
         }
 
-        private String httpRequest(String urlRequest) throws IOException {
-            URL url = new URL(urlRequest);
+        private String httpRequest(Request urlRequest) throws IOException {
+            URL url = new URL(urlRequest.url);
             InputStream inputStream = null;
             String response;
 
@@ -416,6 +416,13 @@ public class AsyncDatabaseConnector {
             urlConnection.setConnectTimeout(CONNECTION_TIMEOUT);
             urlConnection.setRequestMethod(CONNECTION_REQUEST_METHOD);
 
+            OutputStream outputStream = urlConnection.getOutputStream();
+            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+            outputStreamWriter.write(urlRequest.data);
+            outputStreamWriter.flush();
+            outputStreamWriter.close();
+            outputStream.close();
+
             try {
                 urlConnection.connect();
 
@@ -472,9 +479,9 @@ public class AsyncDatabaseConnector {
         }
 
         @Override
-        protected String doInBackground(String... strings) {
+        protected String doInBackground(Request... requests) {
             try {
-                String data = httpRequest(strings[0]);
+                String data = httpRequest(requests[0]);
                 onFinishedListener.onFinished(data, errorString); // Can't be null cos we demand listener in constructor
             } catch (IOException e) {
                 e.printStackTrace();
@@ -497,4 +504,13 @@ public class AsyncDatabaseConnector {
         }
 
     }
+
+    class Request{
+        String url;
+        String data;
+
+        Request(String url){
+            this.url = url;
+        }
+    }
 }

From 7b5e2ddd6dd064c5821923eb55b6b81134959083 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 17 Sep 2014 13:43:35 +0200
Subject: [PATCH 22/33] Support for ICS (API 14)

---
 app/build.gradle | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/build.gradle b/app/build.gradle
index f0efe31..06e72d4 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,7 +6,7 @@ android {
 
     defaultConfig {
         applicationId "info.nerull7.mysqlbrowser"
-        minSdkVersion 15
+        minSdkVersion 14
         targetSdkVersion 19
         versionCode 1
         versionName "1.0"

From 6c842541c3bd579d43572027277c7b416bc85186 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Tue, 30 Sep 2014 15:41:43 +0200
Subject: [PATCH 23/33] Half implementation of SQL Query

 Need to finish it.
---
 app/src/main/AndroidManifest.xml              |   4 +
 .../nerull7/mysqlbrowser/ListActivity.java    |   4 +-
 .../nerull7/mysqlbrowser/SQLActivity.java     |  22 ++++++
 .../nerull7/mysqlbrowser/SQLFragment.java     |  72 ++++++++++++++++++
 .../info/nerull7/mysqlbrowser/Static.java     |   5 ++
 .../db/AsyncDatabaseConnector.java            |  44 ++++++++++-
 .../drawable-hdpi/ic_action_file_upload.png   | Bin 0 -> 380 bytes
 .../drawable-mdpi/ic_action_file_upload.png   | Bin 0 -> 271 bytes
 .../drawable-xhdpi/ic_action_file_upload.png  | Bin 0 -> 466 bytes
 .../drawable-xxhdpi/ic_action_file_upload.png | Bin 0 -> 832 bytes
 app/src/main/res/layout/activity_sql.xml      |   7 ++
 app/src/main/res/layout/fragment_sql.xml      |  24 ++++++
 app/src/main/res/menu/logged.xml              |  12 +++
 app/src/main/res/menu/sql.xml                 |  15 ++++
 app/src/main/res/values/strings.xml           |   5 ++
 15 files changed, 211 insertions(+), 3 deletions(-)
 create mode 100644 app/src/main/java/info/nerull7/mysqlbrowser/SQLActivity.java
 create mode 100644 app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
 create mode 100644 app/src/main/res/drawable-hdpi/ic_action_file_upload.png
 create mode 100644 app/src/main/res/drawable-mdpi/ic_action_file_upload.png
 create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_file_upload.png
 create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_file_upload.png
 create mode 100644 app/src/main/res/layout/activity_sql.xml
 create mode 100644 app/src/main/res/layout/fragment_sql.xml
 create mode 100644 app/src/main/res/menu/logged.xml
 create mode 100644 app/src/main/res/menu/sql.xml

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 39f66fe..f6b00ce 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -34,6 +34,10 @@
             android:name=".ElementActivity"
             android:label="@string/title_activity_element" >
         </activity>
+        <activity
+            android:name=".SQLActivity"
+            android:label="@string/title_activity_sql">
+        </activity>
     </application>
 
     <uses-permission android:name="android.permission.INTERNET" />
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java b/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java
index e2863fd..c88c75f 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java
@@ -33,7 +33,7 @@ public class ListActivity extends Activity {
 
     @Override
     public boolean onCreateOptionsMenu(Menu menu) {
-        getMenuInflater().inflate(R.menu.main, menu);
+        getMenuInflater().inflate(R.menu.logged, menu);
         return true;
     }
 
@@ -47,6 +47,8 @@ public class ListActivity extends Activity {
         if (id == R.id.action_settings) {
             Static.startSettings(this);
             return true;
+        } else if (id == R.id.action_sql){
+            Static.startSQL(this);
         }
         return super.onOptionsItemSelected(item);
     }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLActivity.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLActivity.java
new file mode 100644
index 0000000..396ce94
--- /dev/null
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLActivity.java
@@ -0,0 +1,22 @@
+package info.nerull7.mysqlbrowser;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Created by nerull7 on 30.09.14.
+ */
+public class SQLActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.activity_sql);
+
+        if (savedInstanceState == null) {
+            getFragmentManager().beginTransaction()
+                    .add(R.id.container, new SQLFragment())
+                    .commit();
+        }
+    }
+
+}
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
new file mode 100644
index 0000000..0ba7079
--- /dev/null
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
@@ -0,0 +1,72 @@
+package info.nerull7.mysqlbrowser;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+
+/**
+ * Created by nerull7 on 30.09.14.
+ */
+public class SQLFragment extends Fragment{
+    private EditText sqlEditText;
+    private InputMethodManager inputMethodManager;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        View rootView = inflater.inflate(R.layout.fragment_sql, container, false);
+        sqlEditText = (EditText) rootView.findViewById(R.id.sqlQueryText);
+        setHasOptionsMenu(true);
+        return rootView;
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+        inputMethodManager.showSoftInput(sqlEditText, InputMethodManager.SHOW_FORCED);
+        sqlEditText.requestFocus();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()){
+            case R.id.action_execute:
+                actionExecute();
+                break;
+            case R.id.action_cancel:
+                actionCancel();
+                break;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        inflater.inflate(R.menu.sql, menu);
+        super.onCreateOptionsMenu(menu, inflater);
+    }
+
+    private void actionCancel(){
+        inputMethodManager.hideSoftInputFromWindow(sqlEditText.getWindowToken(), 0);
+        getActivity().finish();
+    }
+
+    private void actionExecute(){
+        String sqlQuery = String.valueOf(sqlEditText.getText());
+        Log.d("SQLQUERY", sqlQuery);
+
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(null);
+        Static.asyncDatabaseConnector.executeSQL(null /*FIXME*/, sqlQuery);
+    }
+}
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
index 6e59148..01d7d35 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
@@ -51,4 +51,9 @@ public class Static {
         builder.create();
         builder.show();
     }
+
+    public static void startSQL(Context context) {
+        Intent intent = new Intent(context, SQLActivity.class);
+        context.startActivity(intent);
+    }
 }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 277dbb7..42a8e04 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -2,6 +2,7 @@ package info.nerull7.mysqlbrowser.db;
 
 import android.content.res.Resources;
 import android.os.AsyncTask;
+import android.util.Log;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -37,6 +38,7 @@ public class AsyncDatabaseConnector {
     public static final String ACTION_ADD_ELEMENT = "addelement";
     public static final String ACTION_UPDATE_ELEMENT = "updateelement";
     public static final String ACTION_REMOVE_ELEMENT = "removeelement";
+    public static final String ACTION_SQL_QUERY = "query";
 
     private String login;
     private String password;
@@ -339,6 +341,44 @@ public class AsyncDatabaseConnector {
         downloader.execute(request);
     }
 
+    public void executeSQL(String database, String query){
+        ArrayList<String> args = new ArrayList();
+        ArrayList<String> values = new ArrayList();
+        final Request request;
+
+        if(database!=null){
+            args.add("d");
+            values.add(database);
+        }
+        args.add("q");
+        values.add(query);
+
+        request = actionUrlBuilder(ACTION_SQL_QUERY, args, values);
+
+        Downloader downloader = new Downloader(new Downloader.OnFinishedListener() {
+            @Override
+            public void onFinished(String data, String error) {
+                String []response = data.split("\n");
+
+                List<String>headerList = null;
+                try {
+                    headerList = parseListFromJSON(response[1]);
+                } catch (JSONException e) { e.printStackTrace(); }
+                if(listReturnListener!=null) {
+                    listReturnListener.onListReturn(headerList);
+                }
+
+                List<List<String>> dataMatrix = null;
+                try {
+                    dataMatrix = parseMatrixFromJSON(response[2]);
+                } catch (JSONException e) { e.printStackTrace(); }
+                if(matrixReturnListener!=null)
+                    matrixReturnListener.onMatrixReturn(dataMatrix);
+            }
+        }, onPostExecuteListener, resources);
+        downloader.execute(request);
+    }
+
     public void setBooleanReturnListener(BooleanReturnListener booleanReturnListener){
         this.booleanReturnListener = booleanReturnListener;
     }
@@ -468,14 +508,14 @@ public class AsyncDatabaseConnector {
                 reader = new BufferedReader(new InputStreamReader(in));
                 String line;
                 while ((line = reader.readLine()) != null) {
-                    streamOutput += line;
+                    streamOutput += line + '\n';
                 }
             } finally {
                 if (reader != null) {
                     reader.close();
                 }
             }
-            return streamOutput;
+            return streamOutput.substring(0, streamOutput.length()-1); // Remove last \n
         }
 
         @Override
diff --git a/app/src/main/res/drawable-hdpi/ic_action_file_upload.png b/app/src/main/res/drawable-hdpi/ic_action_file_upload.png
new file mode 100644
index 0000000000000000000000000000000000000000..4910c3a51ea2c2c6cacf5c1bf24b4022ae8d48bf
GIT binary patch
literal 380
zcmV-?0fYXDP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0003)Nkl<ZXhZFn
zO$x$5424@k&*efqlDH5NaUmW_TzD=8aRw@krEPvD&#@(i(nZtE`;s>_Q&%Iu>XGZO
z9H4Xuy#rJ4z`6mvqCk-risDy|@LPC7AW#6Q_)qa65D0)S@h}K$fFbb^2ulEtcykCV
z0Eu{02nzs>cr%DxfE@8A5IF!A;<F*N0G8sjAT$67@oESu08+dPLISW%W}B|rY#|)j
z9s}`l?6`CCNdRU<!ZT;VBxXy*zc~3M093vU70`OW5yp3hJ3vwv?|{ZqZXvgj#y80~
zZXvhOA6e)m)Up%C!~ew8tkf33nsq2h%S}wJ1$plPkg^Jrayt<HeGIqs&?1oX6&epa
z`*4%{!~wJ=CccAo;P7J$#r4cA6bm*7Rl6_kld~Ro4{&l7iE)4;We1%Him<qaij;jy
a7J35@$Tu-sra*rH0000<MNUMnLSTX+yOps3

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-mdpi/ic_action_file_upload.png b/app/src/main/res/drawable-mdpi/ic_action_file_upload.png
new file mode 100644
index 0000000000000000000000000000000000000000..8374b8d217e64cd212b5d2498b40d8e3cb36fe8f
GIT binary patch
literal 271
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJYo0ESArbD$DG~_>EDn4#?y+jP
zBv8=o_E4{A@gyPk2A%T8s6Ff+lb>=F$u{Izp81?&*(AfBuz607`-E2vHPe6+K{5_K
zPgSg&BG@M+S$g&<9AkVE;kQMZ!?Ho>bY~HZ9s34m-+;qG2aX77l!zry+|MfVyVF;G
zp}>J<%exzxPkCsHy2~0!F)dbf@Z)$PbRunf=3HJ+!}$xMikuo2EL@^-;5kD;fUs6s
z=T`0zo8;bEj&B((7p#8U@l}bjw7ua||B6t_z>~fL$!w)cOIG<8N}5SAG3@@Nq?nw$
Rc@@xy44$rjF6*2UngADGVh8{L

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xhdpi/ic_action_file_upload.png b/app/src/main/res/drawable-xhdpi/ic_action_file_upload.png
new file mode 100644
index 0000000000000000000000000000000000000000..702ea4ef6c6b2c1202ca33a99c04527077a7bfc2
GIT binary patch
literal 466
zcmV;@0WJQCP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0004*Nkl<ZcwX(8
zy$!-J5QSj{Y6^Csqy(`7n=k~MumXaTk{u|hSpggoD54~?eRuDS{Ag&-f8YCjmNK1G
z{+m{Q{s{rlfXWH*3RErto1pg<*tQ0qyiD{2&>Vi<9{dviT_AV?Xb!*Wq<;2*-~r&9
ze0S|v001`u4WKXi?)8V7fCMm<d=~)J1QdXn<Xuca0EkWA#RO{rImts!umq5sJk$g$
z02;|dOt1i;l{~}*Z2%U@o0^~rz$$rD6SM#zk~c9y0{|*{6BDEWJd#&6K?1-lc~ui~
z0nEcLR*_$EmXUQsWw*%j*HHI}to@bc0!UfskW$=JyBCfh9Zmq2blbUUfDkgTfDj;i
zz!(8GK})^Z1V04$3J5LZD<A~OSAeg;2mwBWmiLR#;D^9Y2>B=+@7@G0_b;9s(F4Sr
zw48tdEb0Ek+%zCFrKYn>zxHM>JvglSdYt@X<QhN#G=Nv2?jEoRS74^y#f0-c!}xpZ
z9Jx&}b)91C382_$KpUe0Akf7wLj#J92DC9600Ld?GSwUK1{&5%L0@*GGXMYp07*qo
IM6N<$f@6WctN;K2

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_file_upload.png b/app/src/main/res/drawable-xxhdpi/ic_action_file_upload.png
new file mode 100644
index 0000000000000000000000000000000000000000..8e78556a3584fd8d4870943c6a7e872c4dd5ad21
GIT binary patch
literal 832
zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U}pDpaSW-5dppO`i`h}YRrt=!
ziFa1M=yh=va17WpanU=QN$*_J4Hy^m*qi=cy;`eAk;SL<>yy3f&U190Zmo0T)NwAq
z{*0TG!;VErf$<<q)As8u9u5YL58j$G3JLfqR8;#mu&@Yo+=~-dVBE~v)Be0<>#xj;
zf3xmt79?Kfj5ur`wXs@up10Qutp_;_c8B8Q|5yBS=j?B6ue^5cD$5%Ge;<$Ru3c%y
zIhEy4-`th2<NTdwTC7rekpIS~w`QfqDg}n4=caTB6;6pgV79SYO|euaReVG48wJkH
z_kEkVW=LB<eWbCtVcHGH$rJSYjJPs-WmObIWm1I>^vwloa&2&bv%u3s&^?l+;waxF
z0Xg@JOjSqyZdr7RTre)Xpwe<Qa7n|xjm;`8M*>?KUfl2$b>GXH(jjZY8T)v}_68lG
zOiB0RIHpa<{3>L=3QVvB>e+ETke~5pGP`F%ud+Ym)g*P5zCA1<JwQErg-=u$WC7jw
z#p07dfyJKg$&vGeenpmC*ibfm>HFIvzE^Dc_t$4f{Lf$6-mv!=_nz#S{%P@xm_GbU
zfBdWWsT@<(`u7XBGDg(DyL10a9FxzEA4i1_q-VX-U{s6wlf?PJ*tB#CgRoxRMwSmV
zXIXhQaEkAbVEW<XE30~-r8{1Sv1Zw_KB0s|NA;&M*aZi>a~eE+B<{^Hf91->EHer|
zcB?j=zj7rIx3Pt8jMx8c-+A%lv7P%@*19pSov-c0uwwpe$Jq<78*@2a-xIvv+hKzr
z=Y)m?rh~V$nN$>JIDGgvt3g)S;NIbQUjFy`kuHhS`|lK5+ho*xZ%}t&>T!2w$~j=d
zXcqS+i*teUR?{gA()v|fSuRYxB{fZ;VB_QM3%}3IcRv1ki@nW_^6+iNuflErW&hz%
z`yI=AH08-HZ>E@!kDduNNbU^tXwZ(k6T@Vne4UH4;Ar=3Z-%rdQHqS~Dhi7^5A?)n
zs~iy3&(mX^F)_Q9WyhnVXH^-Di`GtH2;Z|~Crg6cI??<2W&Mdkc8ZgMIfKE|)z4*}
HQ$iB}zV&4+

literal 0
HcmV?d00001

diff --git a/app/src/main/res/layout/activity_sql.xml b/app/src/main/res/layout/activity_sql.xml
new file mode 100644
index 0000000..43ab1db
--- /dev/null
+++ b/app/src/main/res/layout/activity_sql.xml
@@ -0,0 +1,7 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="info.nerull7.mysqlbrowser.ListActivity"
+    tools:ignore="MergeRootFrame" />
diff --git a/app/src/main/res/layout/fragment_sql.xml b/app/src/main/res/layout/fragment_sql.xml
new file mode 100644
index 0000000..1298338
--- /dev/null
+++ b/app/src/main/res/layout/fragment_sql.xml
@@ -0,0 +1,24 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="info.nerull7.mysqlbrowser.DatabaseFragment">
+
+
+    <EditText
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:inputType="textMultiLine"
+        android:ems="10"
+        android:id="@+id/sqlQueryText"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentRight="true"
+        android:layout_alignParentEnd="true"
+        android:gravity="left|top"
+        android:hint="@string/hint_sql_query" >
+        <requestFocus/>
+    </EditText>
+</RelativeLayout>
diff --git a/app/src/main/res/menu/logged.xml b/app/src/main/res/menu/logged.xml
new file mode 100644
index 0000000..5d31f08
--- /dev/null
+++ b/app/src/main/res/menu/logged.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/action_settings"
+        android:title="@string/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never" />
+    <item android:id="@+id/action_sql"
+        android:title="@string/sql_query"
+        android:orderInCategory="200"
+        android:showAsAction="never" />
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/menu/sql.xml b/app/src/main/res/menu/sql.xml
new file mode 100644
index 0000000..5bc3b39
--- /dev/null
+++ b/app/src/main/res/menu/sql.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <item android:id="@+id/action_execute"
+        android:title="@string/action_execute"
+        android:showAsAction="always"
+        android:icon="@drawable/ic_action_file_upload"/>
+
+    <item android:id="@+id/action_cancel"
+        android:title="@string/action_cancel"
+        android:showAsAction="always"
+        android:icon="@drawable/ic_action_delete"/>
+
+</menu>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index ec32bc1..d4c83cb 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -53,5 +53,10 @@
     <string name="save_credentials">Save credentials</string>
     <string name="connector_url">Connector URL</string>
     <string name="no_connection">No Internet Connection</string>
+    <string name="sql_query">SQL Query</string>
+    <string name="title_activity_sql">SQL Query</string>
+    <string name="hint_sql_query">SQL Query</string>
+    <string name="action_cancel">Cancel</string>
+    <string name="action_execute">Execute</string>
 
 </resources>

From b5615d75917fbf055837db1b902f6d157402e661 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 1 Oct 2014 11:40:22 +0200
Subject: [PATCH 24/33] SQL queries

 Full support
---
 .../mysqlbrowser/DatabaseFragment.java        |   6 +
 .../nerull7/mysqlbrowser/ListActivity.java    |   2 +-
 .../mysqlbrowser/SQLEntriesFragment.java      | 245 ++++++++++++++++++
 .../nerull7/mysqlbrowser/SQLFragment.java     |  24 +-
 .../info/nerull7/mysqlbrowser/Static.java     |   3 +-
 .../db/AsyncDatabaseConnector.java            |  35 ++-
 .../main/res/drawable-hdpi/ic_action_info.png | Bin 0 -> 696 bytes
 .../main/res/drawable-mdpi/ic_action_info.png | Bin 0 -> 469 bytes
 .../res/drawable-xhdpi/ic_action_info.png     | Bin 0 -> 891 bytes
 .../res/drawable-xxhdpi/ic_action_info.png    | Bin 0 -> 1577 bytes
 app/src/main/res/values/strings.xml           |   1 +
 11 files changed, 298 insertions(+), 18 deletions(-)
 create mode 100644 app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java
 create mode 100644 app/src/main/res/drawable-hdpi/ic_action_info.png
 create mode 100644 app/src/main/res/drawable-mdpi/ic_action_info.png
 create mode 100644 app/src/main/res/drawable-xhdpi/ic_action_info.png
 create mode 100644 app/src/main/res/drawable-xxhdpi/ic_action_info.png

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
index c70f172..91a6ff4 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
@@ -31,6 +31,12 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
     private ProgressBar progressBar;
     private List<String> databases;
 
+    @Override
+    public void onResume() {
+        super.onResume();
+        Static.asyncDatabaseConnector.setDatabaseInUse(null);
+    }
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
         //Inflate the layout for this fragment
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java b/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java
index c88c75f..3eeb667 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ListActivity.java
@@ -48,7 +48,7 @@ public class ListActivity extends Activity {
             Static.startSettings(this);
             return true;
         } else if (id == R.id.action_sql){
-            Static.startSQL(this);
+            Static.startSQL(this, getIntent().getExtras().getString(Static.DATABASE_NAME_ARG));
         }
         return super.onOptionsItemSelected(item);
     }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java
new file mode 100644
index 0000000..4c1af95
--- /dev/null
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java
@@ -0,0 +1,245 @@
+package info.nerull7.mysqlbrowser;
+
+import android.app.AlertDialog;
+import android.app.Fragment;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
+import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+
+/**
+ * Created by nerull7 on 15.07.14.
+ *
+ * Fragment for showing elements
+ */
+public class SQLEntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener, AsyncDatabaseConnector.StringReturnListener {
+    private static final int HEADER_PADDING_TOP = 15;
+    private static final int HEADER_PADDING_BOTTOM = 15;
+    private static final int HEADER_PADDING_LEFT = 15;
+    private static final int HEADER_PADDING_RIGHT = 15;
+    private static final int ENTRIES_PADDING_TOP = 30;
+    private static final int ENTRIES_PADDING_BOTTOM = 30;
+    private static final int ENTRIES_PADDING_LEFT = 15;
+    private static final int ENTRIES_PADDING_RIGHT = 15;
+
+    private TableLayout entriesTable;
+    private ScrollView entriesScrollView;
+    private FrameLayout headerFrame;
+    private HorizontalScrollView horizontalScrollView;
+    private TableRow.LayoutParams layoutParams;
+
+    private ProgressBar progressBar;
+    private CustomScrollView fakeScrollView;
+    private View dummyView;
+    private boolean showError;
+
+    private Menu menu;
+    private TableRow headerRow;
+    private int[] maxWidth;
+
+    private boolean isFirstCreate;
+    private String errorMessage;
+
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+                             Bundle savedInstanceState) {
+        View rootView = inflater.inflate(R.layout.fragment_entries, container, false);
+        initViewItems(rootView);
+        showError = false;
+        return rootView;
+    }
+
+    private void initViewItems(View rootView){
+        headerFrame = (FrameLayout) rootView.findViewById(R.id.headerFrame);
+        entriesScrollView = (ScrollView) rootView.findViewById(R.id.entriesScrollView);
+        fakeScrollView = (CustomScrollView) rootView.findViewById(R.id.fakeScroll);
+        progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
+        dummyView = rootView.findViewById(R.id.dummyView);
+        horizontalScrollView = (HorizontalScrollView) rootView.findViewById(R.id.horizontalScrollView);
+        entriesTable = new TableLayout(getActivity());
+
+        fakeScrollView.setOnTouchEventListener(new CustomScrollView.OnTouchEventListener() {
+            @Override
+            public boolean onTouchEvent(MotionEvent ev) {
+                ev.offsetLocation(0, headerFrame.getHeight());
+                horizontalScrollView.dispatchTouchEvent(ev);
+                return true;
+            }
+        });
+
+        layoutParams = new TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.MATCH_PARENT);
+    }
+
+    private void setLoading(boolean isLoading){
+        if(menu != null) {
+            menu.findItem(R.id.action_next).setEnabled(!isLoading);
+            menu.findItem(R.id.action_previous).setEnabled(!isLoading);
+        }
+        progressBar.setVisibility(isLoading ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    @Override
+    public void onMatrixReturn(List<List<String>> rows) {
+        // Now we get Rows
+        if(rows!=null) {
+            int background;
+            for (int i = 0; i < rows.size(); i++) {
+                List<String> elements = rows.get(i);
+                TableRow newRow = new TableRow(getActivity());
+
+                if( i%2 == 0 ){ // Two backgrounds for lines for better visibility
+                    background=R.drawable.entries_element_1;
+                } else {
+                    background=R.drawable.entries_element_2;
+                }
+
+                for (int j = 0; j < elements.size(); j++) { // elements.size can be the same as in header so maybe some one number or not
+                    TextView textView = new TextView(getActivity());
+                    textView.setText(elements.get(j));
+                    textView.setLayoutParams(layoutParams);
+                    textView.setPadding(ENTRIES_PADDING_LEFT, ENTRIES_PADDING_TOP, ENTRIES_PADDING_RIGHT, ENTRIES_PADDING_BOTTOM);
+                    textView.setBackgroundResource(background);
+                    textView.setId(j);
+                    newRow.addView(textView);
+                }
+                newRow.setClickable(false);
+                entriesTable.addView(newRow);
+                syncWidthsFirstStage();
+            }
+        } else {
+            entriesTable = null;
+        }
+
+    }
+
+    @Override
+    public void onListReturn(List<String> fieldList) {
+        // First we need header
+        headerRow = new TableRow(getActivity());
+        headerRow.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
+        for (String aFieldList : fieldList) {
+            TextView textView = new TextView(getActivity());
+            textView.setText(aFieldList);
+            textView.setTypeface(null, Typeface.BOLD);
+            textView.setLayoutParams(layoutParams);
+            textView.setBackgroundResource(R.drawable.background_header);
+            textView.setPadding(HEADER_PADDING_LEFT, HEADER_PADDING_TOP, HEADER_PADDING_RIGHT, HEADER_PADDING_BOTTOM);
+            headerRow.addView(textView);
+        }
+    }
+
+    private void syncWidthsFirstStage() { // TODO: Merge with adding columns maybe? Loops -= 3 should be quicker
+        maxWidth = new int[headerRow.getChildCount()];
+        for (int i = 0; i < headerRow.getChildCount(); i++) {
+            TextView textView = (TextView) headerRow.getChildAt(i);
+            textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+            maxWidth[i] = textView.getMeasuredWidth();
+        }
+
+        for (int i = 0; i < entriesTable.getChildCount(); i++) {
+            TableRow tableRow = (TableRow) entriesTable.getChildAt(i);
+            for (int j = 0; j < tableRow.getChildCount(); j++) {
+                TextView textView = (TextView) tableRow.getChildAt(j);
+                textView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+                int width = textView.getMeasuredWidth();
+                if (width > maxWidth[j])
+                    maxWidth[j] = width;
+            }
+        }
+    }
+
+    private void syncWidthsSecondStage() {
+        for(int i=0;i<headerRow.getChildCount();i++){
+            TableRow entriesRow = (TableRow) entriesTable.getChildAt(0);
+
+            TextView tmpEntries = (TextView) entriesRow.getChildAt(i);
+            TextView tmpHeader = (TextView) headerRow.getChildAt(i);
+
+            tmpEntries.setWidth(maxWidth[i]);
+            tmpHeader.setWidth(maxWidth[i]);
+        }
+    }
+
+    private void fakeScroll(){
+        entriesScrollView.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
+        int height = entriesScrollView.getMeasuredHeight();
+        dummyView.setMinimumHeight(height);
+
+        RelativeLayout.LayoutParams fakeScrollLayout = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+        headerFrame.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+        fakeScrollLayout.setMargins(0,headerFrame.getMeasuredHeight(),0,0);
+
+        fakeScrollView.setLayoutParams(fakeScrollLayout);
+    }
+
+//    @Override
+//    public void onResume() {
+//        super.onResume();
+//        if(!isFirstCreate) {
+//            getActivity().finish();
+//        } else {
+//            isFirstCreate = false;
+//        }
+//    }
+
+    @Override
+    public void onPostExecute() {
+        if(!showError) {
+            if (headerFrame.getChildCount() == 0) // You can have only one child
+                headerFrame.addView(headerRow);
+            if (entriesTable != null) {
+                syncWidthsSecondStage();
+                entriesScrollView.addView(entriesTable);
+                fakeScroll();
+            } else {
+                TextView errorMessage = new TextView(getActivity());
+                errorMessage.setText(R.string.error_no_entries);
+                errorMessage.setTypeface(null, Typeface.ITALIC);
+                errorMessage.setClickable(false);
+                entriesScrollView.addView(errorMessage);
+            }
+            setLoading(false);
+        } else {
+            setLoading(false);
+            final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+            builder.setMessage(errorMessage);
+            builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialogInterface, int i) {
+                    getActivity().finish();
+                }
+            });
+            builder.setTitle(R.string.info);
+            builder.setIcon(R.drawable.ic_action_info);
+            builder.create();
+            builder.show();
+        }
+    }
+
+    @Override
+    public void onStringReturn(String data) {
+        errorMessage = data;
+        showError = true;
+    }
+}
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
index 0ba7079..c67bc2e 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
@@ -2,6 +2,7 @@ package info.nerull7.mysqlbrowser;
 
 import android.app.Activity;
 import android.app.Fragment;
+import android.app.FragmentTransaction;
 import android.content.Context;
 import android.os.Bundle;
 import android.util.Log;
@@ -14,12 +15,16 @@ import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 
+import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+
 /**
  * Created by nerull7 on 30.09.14.
  */
-public class SQLFragment extends Fragment{
+public class SQLFragment extends Fragment implements AsyncDatabaseConnector.OnPostExecuteListener {
     private EditText sqlEditText;
     private InputMethodManager inputMethodManager;
+    private SQLEntriesFragment sqlEntriesFragment;
+    private FragmentTransaction fragmentTransaction;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -66,7 +71,20 @@ public class SQLFragment extends Fragment{
         String sqlQuery = String.valueOf(sqlEditText.getText());
         Log.d("SQLQUERY", sqlQuery);
 
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(null);
-        Static.asyncDatabaseConnector.executeSQL(null /*FIXME*/, sqlQuery);
+        fragmentTransaction = getFragmentManager().beginTransaction();
+        sqlEntriesFragment = new SQLEntriesFragment();
+        fragmentTransaction.replace(R.id.container, sqlEntriesFragment);
+        fragmentTransaction.commit();
+
+        Static.asyncDatabaseConnector.setStringReturnListener(sqlEntriesFragment);
+        Static.asyncDatabaseConnector.setListReturnListener(sqlEntriesFragment);
+        Static.asyncDatabaseConnector.setMatrixReturnListener(sqlEntriesFragment);
+        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
+        Static.asyncDatabaseConnector.executeSQL(getActivity().getIntent().getExtras().getString(Static.DATABASE_NAME_ARG), sqlQuery);
+    }
+
+    @Override
+    public void onPostExecute() {
+        sqlEntriesFragment.onPostExecute();
     }
 }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
index 01d7d35..ca0281e 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
@@ -52,8 +52,9 @@ public class Static {
         builder.show();
     }
 
-    public static void startSQL(Context context) {
+    public static void startSQL(Context context, String database) {
         Intent intent = new Intent(context, SQLActivity.class);
+        intent.putExtra(Static.DATABASE_NAME_ARG, database);
         context.startActivity(intent);
     }
 }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
index 42a8e04..0162ca8 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
@@ -360,20 +360,29 @@ public class AsyncDatabaseConnector {
             public void onFinished(String data, String error) {
                 String []response = data.split("\n");
 
-                List<String>headerList = null;
-                try {
-                    headerList = parseListFromJSON(response[1]);
-                } catch (JSONException e) { e.printStackTrace(); }
-                if(listReturnListener!=null) {
-                    listReturnListener.onListReturn(headerList);
-                }
+                if(response[0].equals("OK")) {
+                    List<String> headerList = null;
+                    try {
+                        headerList = parseListFromJSON(response[1]);
+                    } catch (JSONException e) {
+                        e.printStackTrace();
+                    }
+                    if (listReturnListener != null) {
+                        listReturnListener.onListReturn(headerList);
+                    }
 
-                List<List<String>> dataMatrix = null;
-                try {
-                    dataMatrix = parseMatrixFromJSON(response[2]);
-                } catch (JSONException e) { e.printStackTrace(); }
-                if(matrixReturnListener!=null)
-                    matrixReturnListener.onMatrixReturn(dataMatrix);
+                    List<List<String>> dataMatrix = null;
+                    try {
+                        dataMatrix = parseMatrixFromJSON(response[2]);
+                    } catch (JSONException e) {
+                        e.printStackTrace();
+                    }
+                    if (matrixReturnListener != null)
+                        matrixReturnListener.onMatrixReturn(dataMatrix);
+                } else {
+                    if(stringReturnListener!=null)
+                        stringReturnListener.onStringReturn(data);
+                }
             }
         }, onPostExecuteListener, resources);
         downloader.execute(request);
diff --git a/app/src/main/res/drawable-hdpi/ic_action_info.png b/app/src/main/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 0000000000000000000000000000000000000000..75ecc1834177da3ec2c3baae4ede59d3bb423cbc
GIT binary patch
literal 696
zcmV;p0!RIcP)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm0007iNkl<ZXhZE;
zJt#&|82&!O;;(EhvKf>zkg}jClv!jo8Z8J5o6#yVD-?xAi9soYO%^u!U67yWse8Y!
z>)w0rJ@=fi`^u@OudjRFpXZ$Sea~M$C%ol_`=9$KpqN2-fWB<aw5b^=frE_>8t_{O
zQ~~9V<8SzV2JV0x;M&1wT4HGl)WCrbpbe-^=*$E9p8+SpV?x<NcU=ON(9jFC1Espg
z9k~zuo&x*8OHy4r1X^Ka5U5USOws=d-?xGDBzlt&V4M#CT}cdR^gV*i4iGCp;u0u>
z!cm}E!yz4!O9-t4?<(Oq1UT~JMReZvnIu+KGZBZtP!Yl=Y@iuVTT!#1BEW<lQB9-e
z?;BBx9YuhpauU$3HjH0)1*RS5kxpZES_T43Y!rcE2zBaMbmDf_lZ14B4q!g%v||Wu
z1__1{;0ikh=q^$$fzv($3n>V2v0DUwt=M4%`p~&YXQ&(*(*&sY0NC^U6hwg2%+XJ}
zxAE$>LEs(+mYnb`*a{-hgs&4RM&G9B3Y1@Y4FnNj=rDw`*mmL6p^Cs5I<#cbd-!w#
ztf>gF_SYLA;NOhtmQb%NxA?;~Au<P8{&<>7)95_QCQo8)Jeg5%S`s|fQEw;#=EOWu
zk;Z$-+NeTw=@pm(3TJG85{oB5mZn0;<Vx%YgffKK(L@s43ZYm@Y@&?XA`q*Lc4HR$
zGn&M)7BUlC30pG|Yb%k}%^WYnxTXHFK>o??G{ax~frcbRA1O&d{GpyCL|?18OM&Q%
zEs_v_wMY`8FL&Kg5`Dey-5QB~;P8?V{lw%YBKDEbzuOl3%&Iyzh<WH%5wZ4N^+IFK
euqnmj348<P?Wr+h%~m%60000<MNUMnLSTaSOF9z(

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-mdpi/ic_action_info.png b/app/src/main/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 0000000000000000000000000000000000000000..944ab3d239f33c5ab2439a170e146d29744b8c10
GIT binary patch
literal 469
zcmV;`0V@89P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F80004;Nkl<ZSVzT|
zKP*H+5XSFZiCl9vi718SBG*#Wi->46dKaBaC)8JIL`3w|v?3CslnAv(P!ivF_9bgG
z>&@<SnN7azyLYoQzn%U2>NVq1H;!M+1sDZ*3mSGE_(1&vy`^?21%LrN(3A@<#UjK#
zbmf3bc{Bj*<s#IEhDtsD7<@rD&>6(+L`xaKBwDUOBg(*`**jhwLl3d`e*w&((K6J?
z3|=(*#KQ@6EBT25u;=Ul5Zs42kTM|waLhL=q&=1}4#$2tCnSI+7|klu{tTN-XE%p>
zOwr~VHmAN_2*9P*g*3DM4t7V**(&O31prsa9>nF^FCoAJ-pwl<(If|e?Jl767{C_(
zU={{h*!x`xfZOZ#AR~LecktZbw*4WP!0(L&fLGW)Is0+c&4ji+*gl2;+~e00oaD{{
zhB$<HX8g*4IY8<VRLOui1gVp-3V=8XIV35|Fc%=Y3<+Sq5t(nr%!27*L;&;Sm=LBH
zl43J7y^<9WrkBzJ!t`41pG{^TCei_E@@bZEQtM62zKryqGA+LW6Sia_0)jgh00000
LNkvXXu0mjf`4r7(

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xhdpi/ic_action_info.png b/app/src/main/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 0000000000000000000000000000000000000000..6e10fde30dd53259f71fc77743b17ffa6e375b8a
GIT binary patch
literal 891
zcmV->1BCpEP)<h;3K|Lk000e1NJLTq002M$002M;1^@s6s%dfF0009*Nkl<ZcwX(B
zOQ=mz7{~7o1CJ<=n+$Xdr5I7j9e9i|p%h9H0|q803=9km44B-B0fi`qQcN)N7!ZmP
z1EFpPl2?((0Oj|uyLH;mK6|Zo*4let-`Vx=w$J^(_4w`e{Px=Yea5eT<Mr?B0qC^=
z;{>Yg0#jf;8x5eTXfhf<%KsOCzo9Sa9eRttR`G070vJaH7NA9F9-8S{p%2)<LeJ0(
z^xM<l$vg!BJ=tYwIhyWNigKe*m^?&}Mq5g`hoePI0IK*ZG=wHN=I?9v6Nh`~ZY&V7
z04%0J8__i18U@;a#_t+>8tDJmty=&SNofmGKd<A`_;4Bh2+h130JF$+JDL-kc_hC#
zq;mni4@oZ+z+5uhjV6U;n!x8fX`Vr^ebWvBpvvz;8uXfUX&rIa7lJPUHT!)Hdh+=P
zpq6mLr#tun(15qM0e!x#)oDyPiJS&T9{@W^w64*<tkU`aYj!y2;^YcI^ZX8%1RG>?
zp0bp#6I=jju-lJfE^<al?_&<u4DJUb0@Pw@7-?`Uyj%cmz<YJXf+?ws=t(ZkCERa|
zoX;K7yWR}|J^e!{_S(KG0NOho?bHg&TEH5d*GGOTRki@-bpzclszWCL+Rq<Av9`3W
zWvHqJC{JyrkE6EngiZh!;-uwnimOThD*tKpyj?{)0oaU#f*SwBrC`bxUjPSj@C{=%
z6_&zl$9w=NfO)v7wFxZO5&ZrMv=()N`55mB%&4hurzqIVeBp`!ti*6rQ)?1fuB-Un
zcLlHx!?l4Kxwt*RXe4Ji$o&cz=RliV_}z2`ka`BFdKy%{+s*_<U0^E?O9M%}xYYsR
zF$KHi+5*f2Fy94I4}x`c0k1(Y^)y%q0Iz8<^+Ko)0A35B)Jx$y0C+8hHCv?I3{?%l
zdov^eDQAMJ0R(M_%?Cuxhs4wkOb0~;z<gL-5KO-q$y$NwS7U-;`sHZ0g*N?qToBA3
zkPrmZM`W_DVET|$D+II0<T41R4@zbbOdpkPjWC-%EZqvh^l|w-2$LU7<X^fdo}l2W
zx<@yk%;>D2-s+B-PiFEUvU_tMO%;J?)bC}-<Qi4j6ou&lNI`WhrD?te`~g~!#6e&I
RlA-_r002ovPDHLkV1ke}kFx*(

literal 0
HcmV?d00001

diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_info.png b/app/src/main/res/drawable-xxhdpi/ic_action_info.png
new file mode 100644
index 0000000000000000000000000000000000000000..6835e8f56a38d6298b74ec0316501d58e9c8af15
GIT binary patch
literal 1577
zcmV+^2G;qBP)<h;3K|Lk000e1NJLTq003YB003YJ1^@s6;+S_h000H>Nkl<ZcwX&Y
zU5Hji7<T;&Gb15?x~YYPia<p&F9cCRk`TJ+2Z<;U>LT?*M5PiWP(($%&=3?7MIzKL
zf`~$>5WMIIF(FbY*u7FqNHmp7)92a!4(=}B`Och~cg{QW?K|)w?ssP1nddq4`_9bi
z8Dl|}fgV-sW_*kZp!^b;049Jk1Ip&D2ABZK3@Dq=xdt%rV_W?FkALqfbLnM1bpa-$
zRF45OfJcExfQJD7eIhWfRq8wV_g~-!@HcQ3xB^@TF1G&eMNsTWsR=L%1%3v266gh{
z2@&uo(&+<!2Yv-^38fpHObP-p4^IKJTjcZYju}`>D8f150-)M-X$mj_g`W#N4?Gc*
z@eXPC<F_Axv%r5EdC(Bx0Tgrruoz%_o<d;1@g49z@K2K&YFdCfDBLn&dXt5$Ve1b(
zdlLA$Mx3BWn-X9Oa`^%<A85*^FEQ*BegwV-uKOn98m|d5*v7vIJm{LKM4r2ee0&M8
zkBAmx3cxWso0}yWy!B-Svo?I&YL+<H5D&2g;M@Kx@T_=_brSpqW{(4`6`~=A08^2}
zw*k&vyD4yHeGvFdvQW|jko30zE**4ZxP(F-0Vsw@kQ9J#{;Dn}zaX3<9FnRDQUb8e
zU(<!nPT5<|8n6!t?h_;g;ArO!pj$dz*QSLX^HCsZbR;3ba%5tuYp%QOxo=ROuR_Wc
zDgY;0F9V_Jgp@%uF6RlK0p63f5aPJJupY>5hAS-?`+?nn*Rn;30I$F(Yk-Bp8gRmg
z2wwrXs`<J?)59uHZ&sNTh2^1F&9_`W95N2`^9fLU71bxBT+d$%Xe=q;hTR<i*YDc}
z`WH3<<9(S7h{vVuy+AF0f{y@;U}Qx=Mnj@ffNcQXitPg3nI9+#!2EmxoT^j6x&qLR
z_#U9;$x2-S*39jIvwO3y0CcEul~XIEE&zGqswo{hPN9wfeD+;H%Yn`U<sd*G^0^;y
z+HFxsfTxit7uz&L4g!#$kAd?pMAZ@CH6-|)OQI2<$wh#lz`-#W9$W?B*m@%nd(%`^
zo^ug^qqLns<qkYo0p=mGl~wH6@531Q6#qL@#fhr`9QkkrWWk*Qj)XWO>KI%FVDr;$
zKHe&BLVxFm;9XUTxCp>@e@j(D_Iq0fKEz+kX6*wJTm+bf=iV`by%;!vSig0O=_0^F
zB=C}#d5iQpC^#J|0LiBa7V0xV@+m@TaH#>@=aZ7dolfvh{($1xQhmDQW6*JbI8*>`
zH+ft>Z(b>q{5?RY<>+<zJrxo9k(ZA`1xRTKn#)YM;GFx1I3xCMg4jgS!SS%y`zjwP
zHvz7J0y>aNS4OM)09NJAfc6?tA!Tj?u&LY%ly2TK0px4x&=i9OuqG%>px`Em=B*R<
z7a_P4rs<T1p}F+|BE!&>CSth>ATkk4X(=K%0YsJ}Qd*45O#qR_xRjQoa}z*hIXWeW
zOl|^*IAk~y+5kx1-Qz!~%VT3!Q9d!3Boj=<DW6jf5OvC@vMnVi0YtZ@*v71S4X60V
zESk5iiS8nZZ%w3W+nnnzK$Ok7wmscVfId7HWqUf!+X0Pg5uzQ?plKdadLPj8kflBf
zihe|iBG@6l@>&r6kRDCjG1c}0G<Hmt<~0v$S6vaqs}rhx-PJ95y(bzys9j{ut}3`M
zQsY+@(6n9FF(`oAWgRqb*VQOqS5s6#yRfNVe=+Q7iO$NdEK?SM<~cE24UCp^WZdt=
zUC$klAGzovQ3DD)c5S5#<0GDt6o5&y2D}N(^vFvNQIfv6b!bhntBW09C+Qkcm}Q^9
ziCRiWn;a==`xtk)@lLqlHh*O5u>_zUyT0B*@|Xe?=IsLx9fW8?0GhW?n3RanlmLZ!
z`-o5EVW>l^H{egO&sepXYPtpt6{z@-8~x0^F3LrCrVnXy2ivInkXyTvn0?AH!rSGO
zq<zfOhqZ`t>~ppe$qh}K{g-{vIh4iG9$#}5G}^fzD8C7y{2G`5CV(;n%I2*Gm;lNQ
bD4V|rgY8#vZc9{$00000NkvXXu0mjfjmpNB

literal 0
HcmV?d00001

diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d4c83cb..e431c16 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -58,5 +58,6 @@
     <string name="hint_sql_query">SQL Query</string>
     <string name="action_cancel">Cancel</string>
     <string name="action_execute">Execute</string>
+    <string name="info">Information</string>
 
 </resources>

From 7b3b06db5e05b27b200f280d18c4aeacb9fbf9d5 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Thu, 2 Oct 2014 15:31:13 +0200
Subject: [PATCH 25/33] Don't need this permissions.

---
 app/src/main/AndroidManifest.xml | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f6b00ce..2969942 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -42,8 +42,4 @@
 
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-
-    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
-    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-
 </manifest>

From 4fbbabbf81fb372059e0125b1531b6939c7ac8b3 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Mon, 6 Oct 2014 13:04:08 +0200
Subject: [PATCH 26/33] Backup disallowed.

---
 app/src/main/AndroidManifest.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 2969942..5876902 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,7 +3,7 @@
     package="info.nerull7.mysqlbrowser" >
 
     <application
-        android:allowBackup="true"
+        android:allowBackup="false"
         android:icon="@drawable/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/AppTheme" >

From 283af19d923fea15a53bd35c02dfc28c9e4a4784 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Tue, 7 Oct 2014 00:19:52 +0200
Subject: [PATCH 27/33] Bug fix  Missing new values in edit when they out of
 view  SQL Query better view with IME

---
 app/src/main/AndroidManifest.xml              |  6 ++-
 .../mysqlbrowser/ElementArrayAdapter.java     | 48 +++++++++++++------
 .../nerull7/mysqlbrowser/ElementFragment.java | 34 ++++++++-----
 app/src/main/res/layout/fragment_element.xml  |  3 +-
 4 files changed, 62 insertions(+), 29 deletions(-)

diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5876902..b31c3ff 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -32,11 +32,13 @@
         </activity>
         <activity
             android:name=".ElementActivity"
-            android:label="@string/title_activity_element" >
+            android:label="@string/title_activity_element"
+            android:windowSoftInputMode="adjustPan">
         </activity>
         <activity
             android:name=".SQLActivity"
-            android:label="@string/title_activity_sql">
+            android:label="@string/title_activity_sql"
+            android:windowSoftInputMode="adjustResize">
         </activity>
     </application>
 
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
index 9004c95..adc23ba 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
@@ -1,13 +1,14 @@
 package info.nerull7.mysqlbrowser;
 
 import android.content.Context;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
-import android.widget.EditText;
 import android.widget.TextView;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -21,33 +22,52 @@ public class ElementArrayAdapter extends ArrayAdapter<String> {
 
     public ElementArrayAdapter(Context context, int resource, List<String> fields) {
         super(context, resource, fields);
-        this.context = context;
-        this.fields = fields;
-        layout = resource;
-        values = null;
+        init(context, resource, fields);
+        values = new ArrayList<String>();
+        for(String field: fields){
+            values.add("");
+        }
     }
 
     public ElementArrayAdapter(Context context, int resource, List<String> fields, List<String> values) {
-        this(context, resource, fields);
-        this.values = values;
+        super(context, resource, fields);
+        init(context, resource, fields);
+        this.values = new ArrayList<String>();
+        this.values.addAll(values); // Copy
+    }
+
+    private void init(Context context, int resource, List<String> fields){
+        this.context = context;
+        this.fields = fields;
+        layout = resource;
     }
 
     @Override
-    public View getView(int position, View convertView, ViewGroup parent) {
+    public View getView(final int position, View convertView, ViewGroup parent) {
         LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View rowView = layoutInflater.inflate(layout, parent, false);
+        final View rowView = layoutInflater.inflate(layout, parent, false);
 
         TextView textView = (TextView) rowView.findViewById(R.id.textFieldName);
         textView.setText(fields.get(position));
-        if(values != null){
-            TextView textFieldName = (TextView) rowView.findViewById(R.id.editFieldValue);
-            textFieldName.setText(values.get(position));
-        }
-
+        TextView textFieldName = (TextView) rowView.findViewById(R.id.editFieldValue);
+        textFieldName.setText(values.get(position));
+        textFieldName.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(View v, boolean hasFocus) {
+                if (!hasFocus) {
+                    String tmp = String.valueOf(((TextView) v).getText());
+                    values.set(position, tmp);
+                }
+            }
+        });
         return rowView;
     }
 
     public List<String> getFieldArray(){
         return fields;
     }
+
+    public List<String> getValues() {
+        return values;
+    }
 }
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index a26c459..6b84366 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -2,17 +2,22 @@ package info.nerull7.mysqlbrowser;
 
 import android.app.AlertDialog;
 import android.app.Fragment;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsListView;
 import android.widget.EditText;
 import android.widget.ListView;
 import android.widget.ProgressBar;
+import android.widget.RelativeLayout;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -50,6 +55,21 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
         progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);
         listView = (ListView) rootView.findViewById(R.id.listView);
 
+        listView.setOnScrollListener(new AbsListView.OnScrollListener() {
+            @Override
+            public void onScrollStateChanged(AbsListView view, int scrollState) {
+                if(scrollState==SCROLL_STATE_TOUCH_SCROLL) {
+                    listView.requestFocus();
+                    InputMethodManager inputMethodManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+                    inputMethodManager.hideSoftInputFromWindow(listView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+                }
+            }
+
+            @Override
+            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+            }
+        });
+        listView.setItemsCanFocus(true);
         initArguments();
 
         postExecute = POST_EXECUTE_NONE;
@@ -64,9 +84,9 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
         List<String> fields = listAdapter.getFieldArray();
         Static.asyncDatabaseConnector.setStringReturnListener(this);
         if(getArguments().getBoolean(EDIT_ELEMENT))
-            Static.asyncDatabaseConnector.updateElement(tableName, fields, values, getNewValues());
+            Static.asyncDatabaseConnector.updateElement(tableName, fields, values, listAdapter.getValues());
         else
-            Static.asyncDatabaseConnector.addNewElement(tableName, fields, getNewValues());
+            Static.asyncDatabaseConnector.addNewElement(tableName, fields, listAdapter.getValues());
     }
 
     private void actionRemove(){
@@ -137,16 +157,6 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
 
     }
 
-    private List<String> getNewValues(){
-        List<String> newValues = new ArrayList<String>();
-
-        for(int i=0; i<listView.getChildCount();i++){
-            EditText editText = (EditText) listView.getChildAt(i).findViewById(R.id.editFieldValue);
-            newValues.add(String.valueOf(editText.getText()));
-        }
-        return newValues;
-    }
-
     @Override
     public void onStringReturn(String data) {
         message = data;
diff --git a/app/src/main/res/layout/fragment_element.xml b/app/src/main/res/layout/fragment_element.xml
index 3e9e223..c57f312 100644
--- a/app/src/main/res/layout/fragment_element.xml
+++ b/app/src/main/res/layout/fragment_element.xml
@@ -18,6 +18,7 @@
         android:id="@+id/listView"
         android:layout_below="@+id/progressBar"
         android:layout_alignParentLeft="true"
-        android:layout_alignParentStart="true" />
+        android:layout_alignParentStart="true"
+        android:descendantFocusability="afterDescendants"/>
 
 </RelativeLayout>
\ No newline at end of file

From 58fc51b6bd2ff91fe3bde058f1de93051e2e615c Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Tue, 7 Oct 2014 00:33:46 +0200
Subject: [PATCH 28/33] Fix for not updating current field on save

---
 app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java | 1 +
 1 file changed, 1 insertion(+)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index 6b84366..a9f2953 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -120,6 +120,7 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        listView.requestFocus();
         switch (item.getItemId()){
             case R.id.action_save:
                 actionSave();

From 99f56acb4b726a51f2dfa4d7547ada35b001ba2d Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 8 Oct 2014 20:14:23 +0200
Subject: [PATCH 29/33] Rename DatabaseConnector

---
 .../mysqlbrowser/DatabaseFragment.java        | 14 +++++------
 .../nerull7/mysqlbrowser/ElementFragment.java | 24 ++++++++-----------
 .../nerull7/mysqlbrowser/EntriesFragment.java | 20 ++++++++--------
 .../nerull7/mysqlbrowser/LoginFragment.java   | 18 +++++++-------
 .../mysqlbrowser/SQLEntriesFragment.java      |  9 ++-----
 .../nerull7/mysqlbrowser/SQLFragment.java     | 15 ++++++------
 .../info/nerull7/mysqlbrowser/Static.java     |  4 ++--
 .../nerull7/mysqlbrowser/TableFragment.java   | 10 ++++----
 ...eConnector.java => DatabaseConnector.java} | 10 ++++----
 9 files changed, 57 insertions(+), 67 deletions(-)
 rename app/src/main/java/info/nerull7/mysqlbrowser/db/{AsyncDatabaseConnector.java => DatabaseConnector.java} (98%)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
index 91a6ff4..428afa3 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/DatabaseFragment.java
@@ -17,14 +17,14 @@ import android.widget.TextView;
 
 import java.util.List;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 14.07.14.
  *
  * Fragment for showing list of Available Databases for user
  */
-public class DatabaseFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
+public class DatabaseFragment extends Fragment implements AdapterView.OnItemClickListener, DatabaseConnector.ListReturnListener, DatabaseConnector.OnPostExecuteListener {
     private ListView databasesListView;
     private ListAdapter listAdapter;
     private RelativeLayout rootView;
@@ -34,7 +34,7 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
     @Override
     public void onResume() {
         super.onResume();
-        Static.asyncDatabaseConnector.setDatabaseInUse(null);
+        Static.databaseConnector.setDatabaseInUse(null);
     }
 
     @Override
@@ -45,9 +45,9 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
         this.rootView = (RelativeLayout) rootView;
         progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
 
-        Static.asyncDatabaseConnector.setListReturnListener(this);
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
-        Static.asyncDatabaseConnector.getDatabases();
+        Static.databaseConnector.setListReturnListener(this);
+        Static.databaseConnector.setOnPostExecuteListener(this);
+        Static.databaseConnector.getDatabases();
         return rootView;
     }
 
@@ -59,7 +59,7 @@ public class DatabaseFragment extends Fragment implements AdapterView.OnItemClic
             Intent intent = new Intent(getActivity(), ListActivity.class);
             intent.putExtra(Static.FRAGMENT_TO_START, Static.FRAGMENT_TABLE);
             intent.putExtra(Static.DATABASE_NAME_ARG, chosenDatabase);
-            Static.asyncDatabaseConnector.setDatabaseInUse(chosenDatabase);
+            Static.databaseConnector.setDatabaseInUse(chosenDatabase);
             startActivity(intent);
         } else {
             Static.showErrorAlert(getResources().getString(R.string.no_connection), getActivity());
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
index a9f2953..236c769 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementFragment.java
@@ -5,7 +5,6 @@ import android.app.Fragment;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.os.Bundle;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -14,22 +13,19 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AbsListView;
-import android.widget.EditText;
 import android.widget.ListView;
 import android.widget.ProgressBar;
-import android.widget.RelativeLayout;
 
-import java.util.ArrayList;
 import java.util.List;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 2014-08-06.
  *
  * Fragment for editing/adding elements
  */
-public class ElementFragment extends Fragment implements AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.StringReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
+public class ElementFragment extends Fragment implements DatabaseConnector.ListReturnListener, DatabaseConnector.StringReturnListener, DatabaseConnector.OnPostExecuteListener {
     public static final String EDIT_ELEMENT = "edit_element";
     public static final String EDIT_LIST = "edit_element_list";
 
@@ -73,32 +69,32 @@ public class ElementFragment extends Fragment implements AsyncDatabaseConnector.
         initArguments();
 
         postExecute = POST_EXECUTE_NONE;
-        Static.asyncDatabaseConnector.setListReturnListener(this);
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
-        Static.asyncDatabaseConnector.getFields(tableName);
+        Static.databaseConnector.setListReturnListener(this);
+        Static.databaseConnector.setOnPostExecuteListener(this);
+        Static.databaseConnector.getFields(tableName);
 
         return rootView;
     }
 
     private void actionSave(){
         List<String> fields = listAdapter.getFieldArray();
-        Static.asyncDatabaseConnector.setStringReturnListener(this);
+        Static.databaseConnector.setStringReturnListener(this);
         if(getArguments().getBoolean(EDIT_ELEMENT))
-            Static.asyncDatabaseConnector.updateElement(tableName, fields, values, listAdapter.getValues());
+            Static.databaseConnector.updateElement(tableName, fields, values, listAdapter.getValues());
         else
-            Static.asyncDatabaseConnector.addNewElement(tableName, fields, listAdapter.getValues());
+            Static.databaseConnector.addNewElement(tableName, fields, listAdapter.getValues());
     }
 
     private void actionRemove(){
         final List<String> fields = listAdapter.getFieldArray();
-        Static.asyncDatabaseConnector.setStringReturnListener(this);
+        Static.databaseConnector.setStringReturnListener(this);
 
         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
         builder.setMessage(R.string.error_remove);
         builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface dialogInterface, int i) {
-                Static.asyncDatabaseConnector.removeElement(tableName, fields, values);
+                Static.databaseConnector.removeElement(tableName, fields, values);
 //                getActivity().finish();
             }
         });
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
index 9bf12ef..3c8a5b9 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/EntriesFragment.java
@@ -24,14 +24,14 @@ import android.widget.TextView;
 import java.util.ArrayList;
 import java.util.List;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 15.07.14.
  *
  * Fragment for showing elements
  */
-public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.IntegerReturnListener, View.OnClickListener, AsyncDatabaseConnector.OnPostExecuteListener {
+public class EntriesFragment extends Fragment implements DatabaseConnector.MatrixReturnListener, DatabaseConnector.ListReturnListener, DatabaseConnector.IntegerReturnListener, View.OnClickListener, DatabaseConnector.OnPostExecuteListener {
     private static final int HEADER_PADDING_TOP = 15;
     private static final int HEADER_PADDING_BOTTOM = 15;
     private static final int HEADER_PADDING_LEFT = 15;
@@ -75,8 +75,8 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         initListeners();
 
         onPostExecuteListenerExecuted = 0;
-        Static.asyncDatabaseConnector.getFields(tableName);
-        Static.asyncDatabaseConnector.getEntriesCount(tableName);
+        Static.databaseConnector.getFields(tableName);
+        Static.databaseConnector.getEntriesCount(tableName);
 
         return rootView;
     }
@@ -112,10 +112,10 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
     }
 
     private void initListeners(){
-        Static.asyncDatabaseConnector.setIntegerReturnListener(this);
-        Static.asyncDatabaseConnector.setListReturnListener(this);
-        Static.asyncDatabaseConnector.setMatrixReturnListener(this);
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
+        Static.databaseConnector.setIntegerReturnListener(this);
+        Static.databaseConnector.setListReturnListener(this);
+        Static.databaseConnector.setMatrixReturnListener(this);
+        Static.databaseConnector.setOnPostExecuteListener(this);
     }
 
     @Override
@@ -157,7 +157,7 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
         onPostExecuteListenerExecuted--;
 
         setLoading(true);
-        Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page); // get new entries
+        Static.databaseConnector.getRows(tableName, entriesLimit, page); // get new entries
     }
 
     private void addNewElement(){
@@ -240,7 +240,7 @@ public class EntriesFragment extends Fragment implements AsyncDatabaseConnector.
             headerRow.addView(textView);
         }
 
-        Static.asyncDatabaseConnector.getRows(tableName, entriesLimit, page);
+        Static.databaseConnector.getRows(tableName, entriesLimit, page);
     }
 
     @Override
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
index d0a1eee..324c7e4 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/LoginFragment.java
@@ -12,21 +12,21 @@ import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ProgressBar;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 07.07.14.
  *
  * Fragment for login
  */
-public class LoginFragment extends Fragment implements View.OnClickListener, AsyncDatabaseConnector.BooleanReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
+public class LoginFragment extends Fragment implements View.OnClickListener, DatabaseConnector.BooleanReturnListener, DatabaseConnector.OnPostExecuteListener {
     private EditText urlTextbox;
     private EditText loginTextbox;
     private EditText passwordTextbox;
     private ProgressBar progressBar;
     private Button loginButton;
 
-    AsyncDatabaseConnector asyncDatabaseConnector;
+    DatabaseConnector databaseConnector;
 
     private boolean result;
 
@@ -86,10 +86,10 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
         url = urlTextbox.getText().toString();
 
         if(Static.isNetworkConnected(getActivity())) {
-            asyncDatabaseConnector = new AsyncDatabaseConnector(login, password, url, getActivity().getResources());
-            asyncDatabaseConnector.setBooleanReturnListener(this);
-            asyncDatabaseConnector.setOnPostExecuteListener(this);
-            asyncDatabaseConnector.checkLogin();
+            databaseConnector = new DatabaseConnector(login, password, url, getActivity().getResources());
+            databaseConnector.setBooleanReturnListener(this);
+            databaseConnector.setOnPostExecuteListener(this);
+            databaseConnector.checkLogin();
         } else {
             Static.showErrorAlert(getResources().getString(R.string.no_connection), getActivity());
             loginButton.setEnabled(true); // Now we can click button again
@@ -106,13 +106,13 @@ public class LoginFragment extends Fragment implements View.OnClickListener, Asy
     @Override
     public void onPostExecute() {
         if(result) {
-            Static.asyncDatabaseConnector = asyncDatabaseConnector;
+            Static.databaseConnector = databaseConnector;
             Intent intent = new Intent(getActivity(), ListActivity.class);
             intent.putExtra(Static.FRAGMENT_TO_START, Static.FRAGMENT_DATABASE);
             startActivity(intent);
         }
         else {
-            Static.showErrorAlert(AsyncDatabaseConnector.errorMsg, getActivity());
+            Static.showErrorAlert(DatabaseConnector.errorMsg, getActivity());
         }
 
         loginButton.setEnabled(true); // Now we can click button again
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java
index 4c1af95..610a66a 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLEntriesFragment.java
@@ -3,14 +3,10 @@ package info.nerull7.mysqlbrowser;
 import android.app.AlertDialog;
 import android.app.Fragment;
 import android.content.DialogInterface;
-import android.content.Intent;
 import android.graphics.Typeface;
 import android.os.Bundle;
-import android.preference.PreferenceManager;
 import android.view.LayoutInflater;
 import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
@@ -23,17 +19,16 @@ import android.widget.TableLayout;
 import android.widget.TableRow;
 import android.widget.TextView;
 
-import java.util.ArrayList;
 import java.util.List;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 15.07.14.
  *
  * Fragment for showing elements
  */
-public class SQLEntriesFragment extends Fragment implements AsyncDatabaseConnector.MatrixReturnListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener, AsyncDatabaseConnector.StringReturnListener {
+public class SQLEntriesFragment extends Fragment implements DatabaseConnector.MatrixReturnListener, DatabaseConnector.ListReturnListener, DatabaseConnector.OnPostExecuteListener, DatabaseConnector.StringReturnListener {
     private static final int HEADER_PADDING_TOP = 15;
     private static final int HEADER_PADDING_BOTTOM = 15;
     private static final int HEADER_PADDING_LEFT = 15;
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
index c67bc2e..0249a12 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SQLFragment.java
@@ -1,6 +1,5 @@
 package info.nerull7.mysqlbrowser;
 
-import android.app.Activity;
 import android.app.Fragment;
 import android.app.FragmentTransaction;
 import android.content.Context;
@@ -15,12 +14,12 @@ import android.view.ViewGroup;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.EditText;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 30.09.14.
  */
-public class SQLFragment extends Fragment implements AsyncDatabaseConnector.OnPostExecuteListener {
+public class SQLFragment extends Fragment implements DatabaseConnector.OnPostExecuteListener {
     private EditText sqlEditText;
     private InputMethodManager inputMethodManager;
     private SQLEntriesFragment sqlEntriesFragment;
@@ -76,11 +75,11 @@ public class SQLFragment extends Fragment implements AsyncDatabaseConnector.OnPo
         fragmentTransaction.replace(R.id.container, sqlEntriesFragment);
         fragmentTransaction.commit();
 
-        Static.asyncDatabaseConnector.setStringReturnListener(sqlEntriesFragment);
-        Static.asyncDatabaseConnector.setListReturnListener(sqlEntriesFragment);
-        Static.asyncDatabaseConnector.setMatrixReturnListener(sqlEntriesFragment);
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
-        Static.asyncDatabaseConnector.executeSQL(getActivity().getIntent().getExtras().getString(Static.DATABASE_NAME_ARG), sqlQuery);
+        Static.databaseConnector.setStringReturnListener(sqlEntriesFragment);
+        Static.databaseConnector.setListReturnListener(sqlEntriesFragment);
+        Static.databaseConnector.setMatrixReturnListener(sqlEntriesFragment);
+        Static.databaseConnector.setOnPostExecuteListener(this);
+        Static.databaseConnector.executeSQL(getActivity().getIntent().getExtras().getString(Static.DATABASE_NAME_ARG), sqlQuery);
     }
 
     @Override
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
index ca0281e..abf0d41 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/Static.java
@@ -7,7 +7,7 @@ import android.content.Intent;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 14.07.14.
@@ -20,7 +20,7 @@ public class Static {
     public static final String FRAGMENT_DATABASE = "DatabaseFragment";
     public static final String FRAGMENT_TABLE = "TableFragment";
 
-    public static AsyncDatabaseConnector asyncDatabaseConnector = null;
+    public static DatabaseConnector databaseConnector = null;
 
     public static void startSettings(Context context){
         Intent intent = new Intent(context, SettingsActivity.class);
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java
index 1007f2c..25dbedc 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/TableFragment.java
@@ -17,12 +17,12 @@ import android.widget.TextView;
 
 import java.util.List;
 
-import info.nerull7.mysqlbrowser.db.AsyncDatabaseConnector;
+import info.nerull7.mysqlbrowser.db.DatabaseConnector;
 
 /**
  * Created by nerull7 on 14.07.14.
  */
-public class TableFragment extends Fragment implements AdapterView.OnItemClickListener, AsyncDatabaseConnector.ListReturnListener, AsyncDatabaseConnector.OnPostExecuteListener {
+public class TableFragment extends Fragment implements AdapterView.OnItemClickListener, DatabaseConnector.ListReturnListener, DatabaseConnector.OnPostExecuteListener {
     private String databaseName;
     private ListView tablesList;
     private ListAdapter listAdapter;
@@ -38,9 +38,9 @@ public class TableFragment extends Fragment implements AdapterView.OnItemClickLi
         tablesList = (ListView) rootView.findViewById(R.id.tableList);
         this.rootView = (RelativeLayout) rootView;
         progressBar = (ProgressBar) rootView.findViewById(R.id.loginProgressBar);
-        Static.asyncDatabaseConnector.setListReturnListener(this);
-        Static.asyncDatabaseConnector.setOnPostExecuteListener(this);
-        Static.asyncDatabaseConnector.getTables();
+        Static.databaseConnector.setListReturnListener(this);
+        Static.databaseConnector.setOnPostExecuteListener(this);
+        Static.databaseConnector.getTables();
         return rootView;
     }
 
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
similarity index 98%
rename from app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
rename to app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
index 0162ca8..c4f98ad 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/AsyncDatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
@@ -28,7 +28,7 @@ import info.nerull7.mysqlbrowser.R;
  * Created by nerull7 on 07.07.14.
  * Database connector using Async calls
  */
-public class AsyncDatabaseConnector {
+public class DatabaseConnector {
     public static final String ACTION_LOGIN = "login";
     public static final String ACTION_DATABASE_LIST = "dblist";
     public static final String ACTION_TABLE_LIST = "tablelist";
@@ -57,7 +57,7 @@ public class AsyncDatabaseConnector {
     public static String errorMsg;
     private OnPostExecuteListener onPostExecuteListener;
 
-    public AsyncDatabaseConnector(String login, String password, String url, Resources resources){
+    public DatabaseConnector(String login, String password, String url, Resources resources){
         this.login = login;
         this.password = password;
         this.url = url;
@@ -443,10 +443,10 @@ public class AsyncDatabaseConnector {
         private Resources resources;
 
         public static final String CONNECTION_REQUEST_METHOD = "POST";
-        public static final int CONNECTION_TIMEOUT = 15000;
-        public static final int READ_TIMEOUT = 10000;
+        public static final int CONNECTION_TIMEOUT = 15000; // ms
+        public static final int READ_TIMEOUT = 10000; // ms
 
-        Downloader(OnFinishedListener onFinishedListener, OnPostExecuteListener onPostExecuteListener, Resources resources){
+        private Downloader(OnFinishedListener onFinishedListener, OnPostExecuteListener onPostExecuteListener, Resources resources){
             this.onFinishedListener = onFinishedListener;
             this.onPostExecuteListener = onPostExecuteListener;
             this.resources = resources;

From 038a86e35cf55371c43f724359348e79e4e22cef Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 8 Oct 2014 20:39:13 +0200
Subject: [PATCH 30/33] Moved OnPostExecuteListener to Download class

---
 .../nerull7/mysqlbrowser/db/DatabaseConnector.java    | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
index c4f98ad..9fbbd6f 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
@@ -55,7 +55,7 @@ public class DatabaseConnector {
     private MatrixReturnListener matrixReturnListener;
 
     public static String errorMsg;
-    private OnPostExecuteListener onPostExecuteListener;
+    private Downloader.OnPostExecuteListener onPostExecuteListener;
 
     public DatabaseConnector(String login, String password, String url, Resources resources){
         this.login = login;
@@ -408,7 +408,7 @@ public class DatabaseConnector {
         this.matrixReturnListener = matrixReturnListener;
     }
 
-    public void setOnPostExecuteListener(OnPostExecuteListener onPostExecuteListener){
+    public void setOnPostExecuteListener(Downloader.OnPostExecuteListener onPostExecuteListener){
         this.onPostExecuteListener = onPostExecuteListener;
     }
 
@@ -432,9 +432,7 @@ public class DatabaseConnector {
         public void onMatrixReturn(List<List<String>> data);
     }
 
-    public static interface OnPostExecuteListener {
-        void onPostExecute();
-    }
+
 
     private static class Downloader extends AsyncTask<Request, Void, String> {
         private OnFinishedListener onFinishedListener;
@@ -552,6 +550,9 @@ public class DatabaseConnector {
             void onFinished(String data, String error);
         }
 
+        public static interface OnPostExecuteListener {
+            void onPostExecute();
+        }
     }
 
     class Request{

From a6c7b27e2f027b2e5fa1992b10e0678831464f0e Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Wed, 8 Oct 2014 20:44:01 +0200
Subject: [PATCH 31/33] Revert "Moved OnPostExecuteListener to Download class"

This was a mistake

This reverts commit 038a86e35cf55371c43f724359348e79e4e22cef.
---
 .../nerull7/mysqlbrowser/db/DatabaseConnector.java    | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java b/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
index 9fbbd6f..c4f98ad 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/db/DatabaseConnector.java
@@ -55,7 +55,7 @@ public class DatabaseConnector {
     private MatrixReturnListener matrixReturnListener;
 
     public static String errorMsg;
-    private Downloader.OnPostExecuteListener onPostExecuteListener;
+    private OnPostExecuteListener onPostExecuteListener;
 
     public DatabaseConnector(String login, String password, String url, Resources resources){
         this.login = login;
@@ -408,7 +408,7 @@ public class DatabaseConnector {
         this.matrixReturnListener = matrixReturnListener;
     }
 
-    public void setOnPostExecuteListener(Downloader.OnPostExecuteListener onPostExecuteListener){
+    public void setOnPostExecuteListener(OnPostExecuteListener onPostExecuteListener){
         this.onPostExecuteListener = onPostExecuteListener;
     }
 
@@ -432,7 +432,9 @@ public class DatabaseConnector {
         public void onMatrixReturn(List<List<String>> data);
     }
 
-
+    public static interface OnPostExecuteListener {
+        void onPostExecute();
+    }
 
     private static class Downloader extends AsyncTask<Request, Void, String> {
         private OnFinishedListener onFinishedListener;
@@ -550,9 +552,6 @@ public class DatabaseConnector {
             void onFinished(String data, String error);
         }
 
-        public static interface OnPostExecuteListener {
-            void onPostExecute();
-        }
     }
 
     class Request{

From 534824c1c91dee4d8f8019018c6ba20bb2f0d5b2 Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Mon, 13 Oct 2014 15:39:41 +0200
Subject: [PATCH 32/33] Can't use that

---
 .../mysqlbrowser/NumberPickerDialog.java      | 108 ------------------
 .../mysqlbrowser/SettingsFragment.java        |  44 ++++---
 app/src/main/res/xml/settings.xml             |   5 +-
 3 files changed, 23 insertions(+), 134 deletions(-)
 delete mode 100644 app/src/main/java/info/nerull7/mysqlbrowser/NumberPickerDialog.java

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/NumberPickerDialog.java b/app/src/main/java/info/nerull7/mysqlbrowser/NumberPickerDialog.java
deleted file mode 100644
index c4778df..0000000
--- a/app/src/main/java/info/nerull7/mysqlbrowser/NumberPickerDialog.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package info.nerull7.mysqlbrowser;
-
-/**
- * Created by nerull7 on 18.07.14.
- */
-
-import android.app.AlertDialog;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.os.Bundle;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.NumberPicker;
-
-/**
- * A dialog that prompts the user for the message deletion limits.
- */
-public class NumberPickerDialog extends AlertDialog implements DialogInterface.OnClickListener {
-    private static final String NUMBER = "number";
-
-    /**
-     * The callback interface used to indicate the user is done filling in
-     * the time (they clicked on the 'Set' button).
-     */
-    public interface OnNumberSetListener {
-
-        /**
-         * @param number The number that was set.
-         */
-        void onNumberSet(int number);
-    }
-
-    private final NumberPicker mNumberPicker;
-    private final OnNumberSetListener mCallback;
-
-    /**
-     * @param context Parent.
-     * @param callBack How parent is notified.
-     * @param number The initial number.
-     */
-    public NumberPickerDialog(Context context,
-                              OnNumberSetListener callBack,
-                              int number,
-                              int rangeMin,
-                              int rangeMax,
-                              int title) {
-        this(context, AlertDialog.THEME_HOLO_LIGHT, callBack, number, rangeMin, rangeMax, title);
-    }
-
-    /**
-     * @param context Parent.
-     * @param theme the theme to apply to this dialog
-     * @param callBack How parent is notified.
-     * @param number The initial number.
-     */
-    public NumberPickerDialog(Context context,
-                              int theme,
-                              OnNumberSetListener callBack,
-                              int number,
-                              int rangeMin,
-                              int rangeMax,
-                              int title) {
-        super(context, theme);
-        mCallback = callBack;
-
-        setTitle(title);
-
-        setButton(DialogInterface.BUTTON_POSITIVE, context.getText(R.string.set), this);
-        setButton(DialogInterface.BUTTON_NEGATIVE, context.getText(R.string.cancel),
-                (OnClickListener) null);
-
-        LayoutInflater inflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View view = inflater.inflate(R.layout.number_picker_dialog, null);
-        setView(view);
-        mNumberPicker = (NumberPicker) view.findViewById(R.id.number_picker);
-
-        // initialize state
-        mNumberPicker.setMinValue(rangeMin);
-        mNumberPicker.setMaxValue(rangeMax);
-        mNumberPicker.setValue(number);
-        mNumberPicker.setOnLongPressUpdateInterval(100); // make the repeat rate three times as fast
-        // as normal since the range is so large.
-        mNumberPicker.setWrapSelectorWheel(false);       // don't wrap from min->max
-    }
-
-    public void onClick(DialogInterface dialog, int which) {
-        if (mCallback != null) {
-            mNumberPicker.clearFocus();
-            mCallback.onNumberSet(mNumberPicker.getValue());
-            dialog.dismiss();
-        }
-    }
-
-    @Override
-    public Bundle onSaveInstanceState() {
-        Bundle state = super.onSaveInstanceState();
-        state.putInt(NUMBER, mNumberPicker.getValue());
-        return state;
-    }
-
-    @Override
-    public void onRestoreInstanceState(Bundle savedInstanceState) {
-        super.onRestoreInstanceState(savedInstanceState);
-        int number = savedInstanceState.getInt(NUMBER);
-        mNumberPicker.setValue(number);
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/SettingsFragment.java b/app/src/main/java/info/nerull7/mysqlbrowser/SettingsFragment.java
index b49d179..dfff2bc 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/SettingsFragment.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/SettingsFragment.java
@@ -7,7 +7,6 @@ import android.preference.EditTextPreference;
 import android.preference.Preference;
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceManager;
-import android.preference.PreferenceScreen;
 import android.util.Base64;
 
 /**
@@ -15,19 +14,18 @@ import android.util.Base64;
  *
  * Fragment for Preferences/Settings
  */
-public class SettingsFragment extends PreferenceFragment implements NumberPickerDialog.OnNumberSetListener, Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
+public class SettingsFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener {
     public static final String ENTRIES_PAGE_LIMIT = "entries_limit";
+    public static final String ENTRIES_PAGE_LIMIT_STRING = "entries_limit_string";
     public static final String SAVE_SERVER_CREDENTIALS = "save_credentials_enabled";
     public static final String URL_CREDENTIALS = "url";
     public static final String LOGIN_CREDENTIALS = "login";
     public static final String PASSWORD_CREDENTIALS = "password";
 
     public static final int ENTRIES_PAGE_LIMIT_DEF = 20;
-    public static final int ENTRIES_MIN_PAGE = 20;
-    public static final int ENTRIES_MAX_PAGE = 100;
 
     private SharedPreferences preferences;
-    private Preference mEntriesLimit;
+    private EditTextPreference mEntriesLimit;
     private CheckBoxPreference saveCredentials;
     private EditTextPreference connectorUrlCredentials;
     private EditTextPreference loginCredentials;
@@ -49,17 +47,18 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
         addPreferencesFromResource(R.xml.settings);
 
         // Getting fields
-        mEntriesLimit = findPreference(ENTRIES_PAGE_LIMIT);
+        mEntriesLimit = (EditTextPreference) findPreference(ENTRIES_PAGE_LIMIT_STRING);
         saveCredentials = (CheckBoxPreference) findPreference(SAVE_SERVER_CREDENTIALS);
         connectorUrlCredentials = (EditTextPreference) findPreference(URL_CREDENTIALS);
         loginCredentials = (EditTextPreference) findPreference(LOGIN_CREDENTIALS);
         passwordCredentials = (EditTextPreference) findPreference(PASSWORD_CREDENTIALS); // TODO: Some encryption
 
         // Settings fields
-        setEntriesPageLimitSummary();
+        setEntriesPageLimit();
         setPasswordCredentials();
 
         // Settings Listener
+        mEntriesLimit.setOnPreferenceChangeListener(this);
         saveCredentials.setOnPreferenceClickListener(this);
         passwordCredentials.setOnPreferenceChangeListener(this);
     }
@@ -94,6 +93,11 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
         mEntriesLimit.setSummary(getString(R.string.entries_summary, getEntriesPageLimit()));
     }
 
+    private void setEntriesPageLimit(){
+        mEntriesLimit.setText(String.valueOf(getEntriesPageLimit()));
+        setEntriesPageLimitSummary();
+    }
+
     private void setPasswordCredentials(){
         String password;
         password = preferences.getString(PASSWORD_CREDENTIALS, null);
@@ -114,23 +118,6 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
         } catch (Exception e) { e.printStackTrace(); } // TODO: Something useful
     }
 
-    @Override
-    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-        if(preference == mEntriesLimit){
-            new NumberPickerDialog(getActivity(), this, getEntriesPageLimit(), ENTRIES_MIN_PAGE, ENTRIES_MAX_PAGE, R.string.entries_limit).show();
-        }
-
-        return super.onPreferenceTreeClick(preferenceScreen, preference);
-    }
-
-    @Override
-    public void onNumberSet(int number) {
-        SharedPreferences.Editor editor = preferences.edit();
-        editor.putInt(ENTRIES_PAGE_LIMIT, number);
-        editor.apply();
-        setEntriesPageLimitSummary();
-    }
-
     @Override
     public boolean onPreferenceClick(Preference preference) {
         if(preference==saveCredentials){
@@ -146,7 +133,16 @@ public class SettingsFragment extends PreferenceFragment implements NumberPicker
     public boolean onPreferenceChange(Preference preference, Object newValue) {
         if(preference == passwordCredentials){
             savePassword((String) newValue);
+        } else if (preference == mEntriesLimit) {
+            saveEntriesLimit((String) newValue);
         }
         return false;
     }
+
+    private void saveEntriesLimit(String newValue) {
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putInt(ENTRIES_PAGE_LIMIT, Integer.parseInt(newValue));
+        editor.apply();
+        setEntriesPageLimit();
+    }
 }
diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml
index 3cd5391..f310eb7 100644
--- a/app/src/main/res/xml/settings.xml
+++ b/app/src/main/res/xml/settings.xml
@@ -3,8 +3,9 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
     <PreferenceCategory
         android:title="@string/general_category">
-        <Preference
-            android:key="entries_limit"
+        <EditTextPreference
+            android:key="entries_limit_string"
+            android:numeric="integer"
             android:title="@string/entries_limit"
             android:summary="@string/entries_summary"
             />

From 0a37de8e2b9b4e3af19b70daf39aa9545612888b Mon Sep 17 00:00:00 2001
From: Przemek Grondek <github@nerull7.info>
Date: Tue, 14 Oct 2014 09:39:26 +0200
Subject: [PATCH 33/33] Fix NullPointerException

---
 .../info/nerull7/mysqlbrowser/ElementArrayAdapter.java    | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java b/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
index adc23ba..32388b5 100644
--- a/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
+++ b/app/src/main/java/info/nerull7/mysqlbrowser/ElementArrayAdapter.java
@@ -33,7 +33,13 @@ public class ElementArrayAdapter extends ArrayAdapter<String> {
         super(context, resource, fields);
         init(context, resource, fields);
         this.values = new ArrayList<String>();
-        this.values.addAll(values); // Copy
+        if(values!=null) {
+            this.values.addAll(values); // Copy
+        } else {
+            for(int i=0;i<fields.size();i++){
+                this.values.add(new String());
+            }
+        }
     }
 
     private void init(Context context, int resource, List<String> fields){