Skip to content

Commit ff894a5

Browse files
committed
Adds multibook support for the homescreen widget
When adding a widget, there is now an option for choosing the book in addition to the account. Updates to an account in the relevant book will be reflected in the widget. This change handles no migration from the old widget structure. (Users need to remove and re-add widgets)
1 parent ad229ab commit ff894a5

File tree

9 files changed

+153
-36
lines changed

9 files changed

+153
-36
lines changed

app/src/main/java/org/gnucash/android/app/GnuCashApplication.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public void onCreate(){
126126
BookDbHelper bookDbHelper = new BookDbHelper(getApplicationContext());
127127
mBooksDbAdapter = new BooksDbAdapter(bookDbHelper.getWritableDatabase());
128128

129-
initDatabaseAdapters();
129+
initializeDatabaseAdapters();
130130
setDefaultCurrencyCode(getDefaultCurrencyCode());
131131

132132
if (BuildConfig.DEBUG && !isRoboUnitTest())
@@ -137,7 +137,7 @@ public void onCreate(){
137137
* Initialize database adapter singletons for use in the application
138138
* This method should be called every time a new book is opened
139139
*/
140-
private static void initDatabaseAdapters() {
140+
private static void initializeDatabaseAdapters() {
141141
if (mDbHelper != null){ //close if open
142142
mDbHelper.getReadableDatabase().close();
143143
}
@@ -205,15 +205,23 @@ public static BooksDbAdapter getBooksDbAdapter(){
205205
}
206206

207207
/**
208-
* Loads the book with GUID {@code bookUID}
208+
* Loads the book with GUID {@code bookUID} and opens the AccountsActivity
209209
* @param bookUID GUID of the book to be loaded
210210
*/
211211
public static void loadBook(@NonNull String bookUID){
212-
mBooksDbAdapter.setActive(bookUID);
213-
initDatabaseAdapters();
212+
activateBook(bookUID);
214213
AccountsActivity.start(getAppContext());
215214
}
216215

216+
/**
217+
* Activates the book with unique identifer {@code bookUID}, and refreshes the database adapters
218+
* @param bookUID GUID of the book to be activated
219+
*/
220+
public static void activateBook(@NonNull String bookUID){
221+
mBooksDbAdapter.setActive(bookUID);
222+
initializeDatabaseAdapters();
223+
}
224+
217225
/**
218226
* Returns the currently active database in the application
219227
* @return Currently active {@link SQLiteDatabase}

app/src/main/java/org/gnucash/android/db/BookDbHelper.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,16 @@ public void onCreate(SQLiteDatabase db) {
124124

125125
}
126126

127+
/**
128+
* Returns the database for the book
129+
* @param bookUID GUID of the book
130+
* @return SQLiteDatabase of the book
131+
*/
132+
public static SQLiteDatabase getDatabase(String bookUID){
133+
DatabaseHelper dbHelper = new DatabaseHelper(GnuCashApplication.getAppContext(), bookUID);
134+
return dbHelper.getWritableDatabase();
135+
}
136+
127137
/**
128138
* Inserts the book into the database
129139
* @param db Book database

app/src/main/java/org/gnucash/android/db/adapter/BooksDbAdapter.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import org.gnucash.android.ui.settings.PreferenceActivity;
3232
import org.gnucash.android.util.TimestampHelper;
3333

34+
import java.util.List;
35+
3436
/**
3537
* Database adapter for creating/modifying book entries
3638
*/

app/src/main/java/org/gnucash/android/receivers/TransactionAppWidgetProvider.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
import android.content.SharedPreferences.Editor;
2222
import android.preference.PreferenceManager;
2323

24+
import org.gnucash.android.db.adapter.BooksDbAdapter;
25+
import org.gnucash.android.model.Book;
2426
import org.gnucash.android.ui.common.UxArgument;
2527
import org.gnucash.android.ui.homescreen.WidgetConfigurationActivity;
28+
import org.gnucash.android.ui.settings.PreferenceActivity;
2629

2730
/**
2831
* {@link AppWidgetProvider} which is responsible for managing widgets on the homescreen
@@ -43,13 +46,13 @@ public void onUpdate(Context context, AppWidgetManager appWidgetManager,
4346
for (int i=0; i<N; i++) {
4447
int appWidgetId = appWidgetIds[i];
4548

46-
String accountUID = PreferenceManager
47-
.getDefaultSharedPreferences(context)
49+
String accountUID = PreferenceActivity.getActiveBookSharedPreferences()
4850
.getString(UxArgument.SELECTED_ACCOUNT_UID + appWidgetId, null);
4951
if (accountUID == null)
5052
return;
5153

52-
WidgetConfigurationActivity.updateWidget(context, appWidgetId, accountUID);
54+
WidgetConfigurationActivity.updateWidget(context, appWidgetId, accountUID,
55+
BooksDbAdapter.getInstance().getActiveBookUID());
5356
}
5457
}
5558

@@ -62,11 +65,11 @@ public void onEnabled(Context context) {
6265
@Override
6366
public void onDeleted(Context context, int[] appWidgetIds) {
6467
super.onDeleted(context, appWidgetIds);
65-
Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
68+
Editor editor = PreferenceActivity.getActiveBookSharedPreferences().edit();
6669

6770
for (int appWidgetId : appWidgetIds) {
6871
editor.remove(UxArgument.SELECTED_ACCOUNT_UID + appWidgetId);
6972
}
70-
editor.commit();
73+
editor.apply();
7174
}
7275
}

app/src/main/java/org/gnucash/android/ui/common/BaseDrawerActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ protected void onCreate(Bundle savedInstanceState) {
102102
super.onCreate(savedInstanceState);
103103
setContentView(getContentView());
104104

105+
//if a parameter was passed to open an account within a specific book, then switch
106+
String bookUID = getIntent().getStringExtra(UxArgument.BOOK_UID);
107+
if (bookUID != null && !bookUID.equals(BooksDbAdapter.getInstance().getActiveBookUID())){
108+
GnuCashApplication.activateBook(bookUID);
109+
}
110+
105111
ButterKnife.bind(this);
106112
setSupportActionBar(mToolbar);
107113
final ActionBar actionBar = getSupportActionBar();

app/src/main/java/org/gnucash/android/ui/common/FormActivity.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.gnucash.android.R;
3030
import org.gnucash.android.app.GnuCashApplication;
3131
import org.gnucash.android.db.adapter.AccountsDbAdapter;
32+
import org.gnucash.android.db.adapter.BooksDbAdapter;
3233
import org.gnucash.android.ui.account.AccountFormFragment;
3334
import org.gnucash.android.ui.budget.BudgetAmountEditorFragment;
3435
import org.gnucash.android.ui.budget.BudgetFormFragment;
@@ -57,6 +58,12 @@ protected void onCreate(Bundle savedInstanceState) {
5758
super.onCreate(savedInstanceState);
5859
setContentView(R.layout.activity_form);
5960

61+
//if a parameter was passed to open an account within a specific book, then switch
62+
String bookUID = getIntent().getStringExtra(UxArgument.BOOK_UID);
63+
if (bookUID != null && !bookUID.equals(BooksDbAdapter.getInstance().getActiveBookUID())){
64+
GnuCashApplication.activateBook(bookUID);
65+
}
66+
6067
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
6168
setSupportActionBar(toolbar);
6269

app/src/main/java/org/gnucash/android/ui/common/UxArgument.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ public final class UxArgument {
102102
*/
103103
public static final String BUDGET_AMOUNT_LIST = "budget_amount_list";
104104

105+
/**
106+
* GUID of a book which is relevant for a specific action
107+
*/
108+
public static final String BOOK_UID = "book_uid";
109+
105110
//prevent initialization of instances of this class
106111
private UxArgument(){
107112
//prevent even the native class from calling the ctor

app/src/main/java/org/gnucash/android/ui/homescreen/WidgetConfigurationActivity.java

Lines changed: 83 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,39 @@
2525
import android.content.SharedPreferences;
2626
import android.content.SharedPreferences.Editor;
2727
import android.database.Cursor;
28+
import android.database.sqlite.SQLiteDatabase;
2829
import android.os.Bundle;
29-
import android.preference.PreferenceManager;
3030
import android.support.v4.widget.SimpleCursorAdapter;
3131
import android.util.Log;
3232
import android.view.View;
33+
import android.widget.AdapterView;
3334
import android.widget.Button;
3435
import android.widget.RemoteViews;
3536
import android.widget.Spinner;
3637
import android.widget.Toast;
3738

3839
import org.gnucash.android.R;
40+
import org.gnucash.android.db.BookDbHelper;
41+
import org.gnucash.android.db.DatabaseHelper;
42+
import org.gnucash.android.db.DatabaseSchema;
3943
import org.gnucash.android.db.adapter.AccountsDbAdapter;
44+
import org.gnucash.android.db.adapter.BooksDbAdapter;
4045
import org.gnucash.android.model.Account;
46+
import org.gnucash.android.model.Book;
4147
import org.gnucash.android.model.Money;
4248
import org.gnucash.android.receivers.TransactionAppWidgetProvider;
4349
import org.gnucash.android.ui.account.AccountsActivity;
4450
import org.gnucash.android.ui.common.FormActivity;
4551
import org.gnucash.android.ui.common.UxArgument;
52+
import org.gnucash.android.ui.settings.PreferenceActivity;
4653
import org.gnucash.android.ui.transaction.TransactionsActivity;
4754
import org.gnucash.android.util.QualifiedAccountNameCursorAdapter;
4855

4956
import java.util.Locale;
5057

58+
import butterknife.Bind;
59+
import butterknife.ButterKnife;
60+
5161
/**
5262
* Activity for configuration which account to display on a widget.
5363
* The activity is opened each time a widget is added to the homescreen
@@ -57,19 +67,42 @@ public class WidgetConfigurationActivity extends Activity {
5767
private AccountsDbAdapter mAccountsDbAdapter;
5868
private int mAppWidgetId;
5969

60-
private Spinner mAccountsSpinner;
61-
private Button mOkButton;
62-
private Button mCancelButton;
63-
70+
@Bind(R.id.input_accounts_spinner) Spinner mAccountsSpinner;
71+
@Bind(R.id.input_books_spinner) Spinner mBooksSpinner;
72+
73+
@Bind(R.id.btn_save) Button mOkButton;
74+
@Bind(R.id.btn_cancel) Button mCancelButton;
75+
private SimpleCursorAdapter mAccountsCursorAdapter;
76+
77+
6478
@Override
6579
public void onCreate(Bundle savedInstanceState) {
6680
super.onCreate(savedInstanceState);
6781
setContentView(R.layout.widget_configuration);
6882
setResult(RESULT_CANCELED);
69-
70-
mAccountsSpinner = (Spinner) findViewById(R.id.input_accounts_spinner);
71-
mOkButton = (Button) findViewById(R.id.btn_save);
72-
mCancelButton = (Button) findViewById(R.id.btn_cancel);
83+
84+
ButterKnife.bind(this);
85+
86+
BooksDbAdapter booksDbAdapter = BooksDbAdapter.getInstance();
87+
Cursor booksCursor = booksDbAdapter.fetchAllRecords();
88+
String currentBookUID = booksDbAdapter.getActiveBookUID();
89+
90+
//determine the position of the currently active book in the cursor
91+
int position = 0;
92+
while (booksCursor.moveToNext()){
93+
String bookUID = booksCursor.getString(booksCursor.getColumnIndexOrThrow(DatabaseSchema.BookEntry.COLUMN_UID));
94+
if (bookUID.equals(currentBookUID))
95+
break;
96+
++position;
97+
}
98+
99+
SimpleCursorAdapter booksCursorAdapter = new SimpleCursorAdapter(this,
100+
android.R.layout.simple_spinner_item, booksCursor,
101+
new String[]{DatabaseSchema.BookEntry.COLUMN_DISPLAY_NAME},
102+
new int[]{android.R.id.text1}, 0);
103+
booksCursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
104+
mBooksSpinner.setAdapter(booksCursorAdapter);
105+
mBooksSpinner.setSelection(position);
73106

74107
mAccountsDbAdapter = AccountsDbAdapter.getInstance();
75108
Cursor cursor = mAccountsDbAdapter.fetchAllRecordsOrderedByFullName();
@@ -79,10 +112,10 @@ public void onCreate(Bundle savedInstanceState) {
79112
finish();
80113
}
81114

82-
SimpleCursorAdapter cursorAdapter = new QualifiedAccountNameCursorAdapter(this, cursor);
115+
mAccountsCursorAdapter = new QualifiedAccountNameCursorAdapter(this, cursor);
83116
//without this line, the app crashes when a user tries to select an account
84-
cursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
85-
mAccountsSpinner.setAdapter(cursorAdapter);
117+
mAccountsCursorAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
118+
mAccountsSpinner.setAdapter(mAccountsCursorAdapter);
86119

87120
bindListeners();
88121
}
@@ -91,6 +124,24 @@ public void onCreate(Bundle savedInstanceState) {
91124
* Sets click listeners for the buttons in the dialog
92125
*/
93126
private void bindListeners() {
127+
mBooksSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
128+
@Override
129+
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
130+
Book book = BooksDbAdapter.getInstance().getRecord(id);
131+
SQLiteDatabase db = new DatabaseHelper(WidgetConfigurationActivity.this, book.getUID()).getWritableDatabase();
132+
mAccountsDbAdapter = new AccountsDbAdapter(db);
133+
134+
Cursor cursor = mAccountsDbAdapter.fetchAllRecordsOrderedByFullName();
135+
mAccountsCursorAdapter.swapCursor(cursor);
136+
mAccountsCursorAdapter.notifyDataSetChanged();
137+
}
138+
139+
@Override
140+
public void onNothingSelected(AdapterView<?> parent) {
141+
//nothing to see here, move along
142+
}
143+
});
144+
94145
mOkButton.setOnClickListener(new View.OnClickListener() {
95146

96147
@Override
@@ -110,12 +161,17 @@ public void onClick(View v) {
110161

111162
long accountId = mAccountsSpinner.getSelectedItemId();
112163
String accountUID = mAccountsDbAdapter.getUID(accountId);
113-
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(WidgetConfigurationActivity.this);
164+
165+
long bookId = mBooksSpinner.getSelectedItemId();
166+
String bookUID = BooksDbAdapter.getInstance().getUID(bookId);
167+
168+
SharedPreferences prefs = PreferenceActivity.getBookSharedPreferences(bookUID);
169+
//PreferenceManager.getDefaultSharedPreferences(WidgetConfigurationActivity.this);
114170
Editor editor = prefs.edit();
115171
editor.putString(UxArgument.SELECTED_ACCOUNT_UID + mAppWidgetId, accountUID);
116-
editor.commit();
172+
editor.apply();
117173

118-
updateWidget(WidgetConfigurationActivity.this, mAppWidgetId, accountUID);
174+
updateWidget(WidgetConfigurationActivity.this, mAppWidgetId, accountUID, bookUID);
119175

120176
Intent resultValue = new Intent();
121177
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
@@ -137,14 +193,16 @@ public void onClick(View v) {
137193
* Updates the widget with id <code>appWidgetId</code> with information from the
138194
* account with record ID <code>accountId</code>
139195
* If the account has been deleted, then a notice is posted in the widget
140-
* @param appWidgetId ID of the widget to be updated
196+
* @param appWidgetId ID of the widget to be updated
141197
* @param accountUID GUID of the account tied to the widget
198+
* @param bookUID GUID of the book with the relevant account
142199
*/
143-
public static void updateWidget(final Context context, int appWidgetId, String accountUID) {
200+
public static void updateWidget(final Context context, int appWidgetId, String accountUID, String bookUID) {
144201
Log.i("WidgetConfiguration", "Updating widget: " + appWidgetId);
145202
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
146203

147-
AccountsDbAdapter accountsDbAdapter = AccountsDbAdapter.getInstance();
204+
AccountsDbAdapter accountsDbAdapter = new AccountsDbAdapter(BookDbHelper.getDatabase(bookUID));
205+
148206
final Account account;
149207
try {
150208
account = accountsDbAdapter.getRecord(accountUID);
@@ -161,9 +219,9 @@ public static void updateWidget(final Context context, int appWidgetId, String a
161219
views.setOnClickPendingIntent(R.id.widget_layout, pendingIntent);
162220
views.setOnClickPendingIntent(R.id.btn_new_transaction, pendingIntent);
163221
appWidgetManager.updateAppWidget(appWidgetId, views);
164-
Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
222+
Editor editor = PreferenceActivity.getActiveBookSharedPreferences().edit(); //PreferenceManager.getDefaultSharedPreferences(context).edit();
165223
editor.remove(UxArgument.SELECTED_ACCOUNT_UID + appWidgetId);
166-
editor.commit();
224+
editor.apply();
167225
return;
168226
}
169227

@@ -183,6 +241,7 @@ public static void updateWidget(final Context context, int appWidgetId, String a
183241
accountViewIntent.setAction(Intent.ACTION_VIEW);
184242
accountViewIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
185243
accountViewIntent.putExtra(UxArgument.SELECTED_ACCOUNT_UID, accountUID);
244+
accountViewIntent.putExtra(UxArgument.BOOK_UID, bookUID);
186245
PendingIntent accountPendingIntent = PendingIntent
187246
.getActivity(context, appWidgetId, accountViewIntent, 0);
188247
views.setOnClickPendingIntent(R.id.widget_layout, accountPendingIntent);
@@ -191,6 +250,7 @@ public static void updateWidget(final Context context, int appWidgetId, String a
191250
newTransactionIntent.setAction(Intent.ACTION_INSERT_OR_EDIT);
192251
newTransactionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
193252
newTransactionIntent.putExtra(UxArgument.FORM_TYPE, FormActivity.FormType.TRANSACTION.name());
253+
newTransactionIntent.putExtra(UxArgument.BOOK_UID, bookUID);
194254
newTransactionIntent.putExtra(UxArgument.SELECTED_ACCOUNT_UID, accountUID);
195255
PendingIntent pendingIntent = PendingIntent
196256
.getActivity(context, appWidgetId, newTransactionIntent, 0);
@@ -212,7 +272,8 @@ public static void updateAllWidgets(final Context context){
212272
//update widgets asynchronously so as not to block method which called the update
213273
//inside the computation of the account balance
214274
new Thread(new Runnable() {
215-
SharedPreferences defaultSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
275+
SharedPreferences defaultSharedPrefs = PreferenceActivity.getActiveBookSharedPreferences();
276+
//PreferenceManager.getDefaultSharedPreferences(context);
216277

217278
@Override
218279
public void run() {
@@ -223,7 +284,7 @@ public void run() {
223284
if (accountUID == null)
224285
continue;
225286

226-
updateWidget(context, widgetId, accountUID);
287+
updateWidget(context, widgetId, accountUID, BooksDbAdapter.getInstance().getActiveBookUID());
227288
}
228289
}
229290
}).start();

0 commit comments

Comments
 (0)