arg0) {
- switch (arg0.getId()) {
- case TRANSACTION_CURSOR:
- mTransactionsCursor = null;
- mAdapter.swapCursor(null);
- hasItems = false;
- break;
- case SUM_CURSOR:
- mappedCategories = false;
- mappedPayees = false;
- mappedMethods = false;
- break;
- }
- }
-
- public boolean isFiltered() {
- return !getFilter().isEmpty();
- }
-
- public boolean hasItems() {
- return hasItems;
- }
-
- public boolean hasMappedCategories() {
- return mappedCategories;
- }
-
- abstract @Nullable Long resolveBudget(int headerId);
-
- private class MyGroupedAdapter extends TransactionAdapter implements SectionIndexingStickyListHeadersAdapter {
- private final LayoutInflater inflater;
- private final SparseBooleanArray sumLineState = new SparseBooleanArray();
-
- private MyGroupedAdapter(Context context, int layout, Cursor c, int flags) {
- super(context, layout, c, flags, currencyFormatter, prefHandler, currencyContext,
- id -> checkSealed(new long[]{id}, () -> viewModel.toggleCrStatus(id)));
- inflater = LayoutInflater.from(getActivity());
- }
-
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- if (!binding.list.isHeaderCollapsed(headerId(cursor)))
- super.bindView(view, context, cursor);
- }
-
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- if (binding.list.isHeaderCollapsed(headerId(cursor))) {
- return new View(context);
- } else {
- return super.newView(context, cursor, parent);
- }
- }
-
- private int headerId(Cursor cursor) {
- return calculateHeaderId(cursor.getInt(getColumnIndexForYear()), getSecond(cursor));
- }
-
- @Override
- public int getItemViewType(int position) {
- return binding.list.isHeaderCollapsed(getHeaderId(position)) ? 0 : 1;
- }
-
- @Override
- public int getViewTypeCount() {
- return 2;
- }
-
- @Override
- public View getHeaderView(int position, View convertView, ViewGroup parent) {
- HeaderViewHolder holder = null;
- final int headerId = getHeaderIdInt(position);
- final Long budget = licenceHandler.hasTrialAccessTo(ContribFeature.BUDGET) ? resolveBudget(headerId) : null;
- final boolean withBudget = BaseTransactionList.this.getFilter().isEmpty() && budget != null;
-
- if (convertView != null) {
- holder = (HeaderViewHolder) convertView.getTag();
- boolean holderHasBudget = holder.budgetProgress() != null;
- if (withBudget != holderHasBudget) holder = null;
- }
- if (holder == null) {
- ViewBinding binding = withBudget ? HeaderWithBudgetBinding.inflate(inflater, parent, false) : HeaderBinding.inflate(inflater, parent, false);
- convertView = binding.getRoot();
- holder = new HeaderViewHolder(binding);
- convertView.setTag(holder);
- }
- boolean sumLineVisibility = sumLineState.get(headerId, prefHandler.getBoolean(PrefKey.GROUP_HEADER, true));
- holder.sumLine().setVisibility(sumLineVisibility ? View.VISIBLE : View.GONE);
- HeaderViewHolder finalHolder = holder;
- holder.interimBalance().setOnClickListener(v -> {
- final boolean oldState = finalHolder.sumLine().getVisibility() == View.VISIBLE;
- sumLineState.put(headerId, !oldState);
- finalHolder.sumLine().setVisibility(oldState ? View.GONE : View.VISIBLE);
- });
- if (mAccount.getGrouping() != Grouping.NONE) {
- holder.headerIndicator().setVisibility(View.VISIBLE);
- holder.headerIndicator().setExpanded(!binding.list.isHeaderCollapsed(headerId));
- holder.headerIndicator().setOnClickListener(v -> finalHolder.headerIndicator().rotate(
- !binding.list.isHeaderCollapsed(headerId), expanded -> {
- if (binding != null) {
- if (expanded) {
- binding.list.expand(headerId);
- mAdapter.notifyDataSetChanged();
- persistCollapsedHeaderIds();
- finalHolder.dividerBottom().setVisibility(View.VISIBLE);
- } else {
- binding.list.collapse(headerId);
- persistCollapsedHeaderIds();
- finalHolder.dividerBottom().setVisibility(View.GONE);
- }
- }
- }));
- } else {
- holder.headerIndicator().setVisibility(View.GONE);
- }
-
- Cursor c = getCursor();
- if (c != null) {
- c.moveToPosition(position);
- fillSums(holder, headerId, budget);
- holder.text().setText(mAccount.getGrouping().getDisplayTitle(getActivity(), c.getInt(getColumnIndexForYear()), getSecond(c),
- DateInfo.fromCursor(c)));
- }
- return convertView;
- }
-
- @SuppressLint("SetTextI18n")
- private void fillSums(HeaderViewHolder holder, int headerId, Long budget) {
- Long[] data = headerData != null ? headerData.get(headerId) : null;
- if (data != null) {
- holder.sumIncome().setText("⊕ " + convAmount(currencyFormatter, data[0], mAccount.getCurrencyUnit()));
- final long expensesSum = -data[1];
- holder.sumExpense().setText("⊖ " + convAmount(currencyFormatter, expensesSum, mAccount.getCurrencyUnit()));
- holder.sumTransfer().setText(Transfer.BI_ARROW + " " + convAmount(currencyFormatter,
- data[2], mAccount.getCurrencyUnit()));
- String formattedDelta = String.format("%s %s", Long.signum(data[4]) > -1 ? "+" : "-",
- convAmount(currencyFormatter, Math.abs(data[4]), mAccount.getCurrencyUnit()));
- convAmount(currencyFormatter, Math.abs(data[4]), mAccount.getCurrencyUnit());
- holder.interimBalance().setText(
- BaseTransactionList.this.getFilter().isEmpty() && !mAccount.isHomeAggregate() ? String.format("%s %s = %s",
- convAmount(currencyFormatter, data[3], mAccount.getCurrencyUnit()), formattedDelta,
- convAmount(currencyFormatter, data[5], mAccount.getCurrencyUnit())) :
- formattedDelta);
- final DonutProgress budgetProgress = holder.budgetProgress();
- if (budgetProgress != null) {
- if (budget != null) {
- int progress = budget == 0L ? 100 : Math.round(expensesSum * 100F / budget);
- UiUtils.configureProgress(budgetProgress, progress);
- budgetProgress.setFinishedStrokeColor(mAccount.color);
- budgetProgress.setUnfinishedStrokeColor(getComplementColor(mAccount.color));
- budgetProgress.setOnClickListener(v -> {
- ((ProtectedFragmentActivity) requireActivity()).contribFeatureRequested(ContribFeature.BUDGET,
- new Pair<>(viewModel.getDefaultBudget(mAccount.getAccountId(), mAccount.getGrouping()), headerId));
- });
- }
- }
- }
- }
-
- @Override
- public long getHeaderId(int position) {
- return getHeaderIdInt(position);
- }
-
- private int getHeaderIdInt(int position) {
- Cursor c = getCursor();
- if (c == null) return 0;
- c.moveToPosition(position);
- return calculateHeaderId(c.getInt(getColumnIndexForYear()), getSecond(c));
- }
-
-
- private int getSectioningId(int position) {
- Cursor c = getCursor();
- return c.moveToPosition(position) ? calculateHeaderId(c.getInt(columnIndexYear), c.getInt(columnIndexMonth), Grouping.MONTH) : 0;
- }
-
- private int getSecond(Cursor c) {
- switch (mAccount.getGrouping()) {
- case DAY:
- return c.getInt(columnIndexDay);
- case WEEK:
- return c.getInt(columnIndexWeek);
- case MONTH:
- return c.getInt(columnIndexMonth);
- default:
- return 0;
- }
- }
-
- private int getColumnIndexForYear() {
- switch (mAccount.getGrouping()) {
- case WEEK:
- return columnIndexYearOfWeekStart;
- case MONTH:
- return columnIndexYearOfMonthStart;
- default:
- return columnIndexYear;
- }
- }
-
- @Override
- public Object[] getSections() {
- return sections;
- }
-
- /**
- * inspired by {@link android.widget.AlphabetIndexer}
- * {@inheritDoc}
- */
- @Override
- public int getPositionForSection(int sectionIndex) {
- // Check bounds
- if (sectionIds == null) {
- return 0;
- }
- if (sectionIndex >= sections.length) {
- sectionIndex = sections.length - 1;
- if (sectionIndex <= 0) {
- return 0;
- }
- }
-
- int count = mTransactionsCursor.getCount();
- int start = 0;
- int end = count;
- int pos;
- int targetHeaderId = sectionIds[sectionIndex];
-
- // Check map
- if (Integer.MIN_VALUE != (pos = mSectionCache.get(targetHeaderId, Integer.MIN_VALUE))) {
- // Is it approximate? Using negative value to indicate that it's
- // an approximation and positive value when it is the accurate
- // position.
- if (pos < 0) {
- pos = -pos;
- end = pos;
- } else {
- // Not approximate, this is the confirmed start of section, return it
- Timber.d("getPositionForSection from cache %d: %d", sectionIndex, pos);
- return pos;
- }
- }
-
- // Do we have the position of the previous section?
- if (sectionIndex > 0) {
- int prevLetterPos = mSectionCache.get(sectionIds[sectionIndex - 1], Integer.MIN_VALUE);
- if (prevLetterPos != Integer.MIN_VALUE) {
- start = Math.abs(prevLetterPos);
- }
- }
-
- // Now that we have a possibly optimized start and end, let's binary search
-
- pos = (end + start) / 2;
-
- while (pos < end) {
- // Get letter at pos
- int curHeaderId = getSectioningId(pos);
-
- int diff = Utils.compare(curHeaderId, targetHeaderId);
- if (diff != 0) {
- if (mAccount.getSortDirection().equals(SortDirection.DESC)) diff = -diff;
- // Enter approximation in hash if a better solution doesn't exist
- int curPos = mSectionCache.get(curHeaderId, Integer.MIN_VALUE);
- if (curPos == Integer.MIN_VALUE || Math.abs(curPos) > pos) {
- // Negative pos indicates that it is an approximation
- mSectionCache.put(curHeaderId, -pos);
- }
- if (diff < 0) {
- start = pos + 1;
- if (start >= count) {
- pos = count;
- break;
- }
- } else {
- end = pos;
- }
- } else {
- // They're the same, but that doesn't mean it's the start
- if (start == pos) {
- // This is it
- break;
- } else {
- // Need to go further lower to find the starting row
- end = pos;
- }
- }
- pos = (start + end) / 2;
- }
- mSectionCache.put(targetHeaderId, pos);
- Timber.d("getPositionForSection %d: %d", sectionIndex, pos);
- return pos;
- }
-
- @Override
- public int getSectionForPosition(int position) {
- if (sectionIds == null) return 0;
- final int indexOfKey = IntStream.range(0, sectionIds.length)
- .filter(i -> sectionIds[i] == getSectioningId(position))
- .findFirst().orElse(0);
- Timber.d("getSectionForPosition %d: %d", position, indexOfKey);
- return indexOfKey;
- }
- }
-
- static class HeaderViewHolder {
- private final ViewBinding viewBinding;
-
- TextView interimBalance() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).headerLine.interimBalance : ((HeaderWithBudgetBinding) viewBinding).interimBalance;
- }
-
- TextView text() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).headerLine.text : ((HeaderWithBudgetBinding) viewBinding).text;
- }
-
- ViewGroup sumLine() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).sumLine : ((HeaderWithBudgetBinding) viewBinding).sumLine;
- }
-
- TextView sumIncome() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).sumIncome : ((HeaderWithBudgetBinding) viewBinding).sumIncome;
- }
-
- TextView sumExpense() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).sumExpense : ((HeaderWithBudgetBinding) viewBinding).sumExpense;
- }
-
- TextView sumTransfer() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).sumTransfer : ((HeaderWithBudgetBinding) viewBinding).sumTransfer;
- }
-
- @Nullable
- DonutProgress budgetProgress() {
- return viewBinding instanceof HeaderBinding ? null : ((HeaderWithBudgetBinding) viewBinding).budgetProgress;
- }
-
- View dividerBottom() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).dividerBottom : ((HeaderWithBudgetBinding) viewBinding).dividerBottom;
- }
-
- ExpansionHandle headerIndicator() {
- return viewBinding instanceof HeaderBinding ? ((HeaderBinding) viewBinding).expansionHandle.getRoot() : ((HeaderWithBudgetBinding) viewBinding).expansionHandle.getRoot();
- }
-
- HeaderViewHolder(ViewBinding viewBinding) {
- this.viewBinding = viewBinding;
- }
- }
-
- @Override
- public void onHeaderClick(StickyListHeadersListView l, View header,
- int itemPosition, long headerId, boolean currentlySticky) {
- }
-
- private void persistCollapsedHeaderIds() {
- PreferenceUtilsKt.putLongList(prefHandler, collapsedHeaderIdsPrefKey(), binding.list.getCollapsedHeaderIds());
- }
-
- private String collapsedHeaderIdsPrefKey() {
- return String.format(Locale.ROOT, "collapsedHeaders_%d_%s", mAccount.getId(), mAccount.getGrouping());
- }
-
- protected boolean isTransferAtPosition(int position) {
- if (mTransactionsCursor != null) {
- return mTransactionsCursor.moveToPosition(position) &&
- DbUtils.getLongOr0L(mTransactionsCursor, KEY_TRANSFER_ACCOUNT) != 0L;
- }
- return false;
- }
-
- protected boolean isSplitAtPosition(int position) {
- if (mTransactionsCursor != null) {
- return mTransactionsCursor.moveToPosition(position) &&
- SPLIT_CATID.equals(DbUtils.getLongOrNull(mTransactionsCursor, KEY_CATID));
- }
- return false;
- }
-
- protected boolean isVoidAtPosition(int position) {
- if (mTransactionsCursor != null) {
- if (mTransactionsCursor.moveToPosition(position)) {
- CrStatus status;
- try {
- status = CrStatus.valueOf(mTransactionsCursor.getString(columnIndexCrStatus));
- } catch (IllegalArgumentException ex) {
- status = CrStatus.UNRECONCILED;
- }
- return status.equals(CrStatus.VOID);
- }
- }
- return false;
- }
-
- @SuppressLint("NewApi")
- public void onDrawerOpened() {
- if (mActionMode != null) {
- mCheckedListItems = binding.list.getWrappedList().getCheckedItemPositions().clone();
- mActionMode.finish();
- }
- }
-
- public void onDrawerClosed() {
- if (mCheckedListItems != null) {
- for (int i = 0; i < mCheckedListItems.size(); i++) {
- if (mCheckedListItems.valueAt(i)) {
- binding.list.getWrappedList().setItemChecked(mCheckedListItems.keyAt(i), true);
- }
- }
- }
- mCheckedListItems = null;
- }
-
- public void addFilterCriteria(Criterion c) {
- filterPersistence.addCriteria(c);
- refreshAfterFilterChange();
- }
-
- protected void refreshAfterFilterChange() {
- refresh(true);
- }
-
- /**
- * Removes a given filter
- *
- * @return true if the filter was set and successfully removed, false otherwise
- */
- protected boolean removeFilter(int id) {
- boolean isFiltered = filterPersistence.removeFilter(id);
- if (isFiltered) {
- refreshAfterFilterChange();
- }
- return isFiltered;
- }
-
- private String prefNameForCriteria() {
- return TransactionListViewModel.Companion.prefNameForCriteria(getArguments().getLong(KEY_ACCOUNTID));
- }
-
- public void clearFilter() {
- filterPersistence.clearFilter();
- refreshAfterFilterChange();
- }
-
- @Override
- public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
- inflater.inflate(R.menu.expenses, menu);
- inflater.inflate(R.menu.grouping, menu);
- }
-
- private void configureFilterCard() {
- binding.filterCard.setVisibility(getFilter().isEmpty() ? View.GONE : View.VISIBLE);
- if (!getFilter().isEmpty()) {
- addChipsBulk(binding.filter, Stream.of(getFilter().getCriteria()).map(criterion -> criterion.prettyPrint(getContext())).collect(Collectors.toList()), null);
- }
- }
-
- @Override
- public void onPrepareOptionsMenu(@NonNull Menu menu) {
- super.onPrepareOptionsMenu(menu);
- if (mAccount == null || getActivity() == null) {
- //mAccount seen in report 3331195c529454ca6b25a4c5d403beda
- //getActivity seen in report 68a501c984bdfcc95b40050af4f815bf
- return;
- }
- MenuItem searchMenu = menu.findItem(R.id.SEARCH_COMMAND);
- if (searchMenu != null) {
- searchMenu.setChecked(!getFilter().isEmpty());
- MenuUtilsKt.checkMenuIcon(searchMenu);
- SubMenu filterMenu = searchMenu.getSubMenu();
- for (int i = 0; i < filterMenu.size(); i++) {
- MenuItem filterItem = filterMenu.getItem(i);
- boolean enabled = true;
- int itemId = filterItem.getItemId();
- if (itemId == R.id.FILTER_CATEGORY_COMMAND) {
- enabled = mappedCategories;
- } else if (itemId == R.id.FILTER_STATUS_COMMAND) {
- enabled = mAccount.isAggregate() || !mAccount.getType().equals(AccountType.CASH);
- } else if (itemId == R.id.FILTER_PAYEE_COMMAND) {
- enabled = mappedPayees;
- } else if (itemId == R.id.FILTER_METHOD_COMMAND) {
- enabled = mappedMethods;
- } else if (itemId == R.id.FILTER_TRANSFER_COMMAND) {
- enabled = hasTransfers;
- } else if (itemId == R.id.FILTER_TAG_COMMAND) {
- enabled = hasTags;
- } else if (itemId == R.id.FILTER_ACCOUNT_COMMAND) {
- enabled = mAccount.isAggregate();
- }
- Criterion c = getFilter().get(filterItem.getItemId());
- Utils.menuItemSetEnabledAndVisible(filterItem, enabled || c != null);
- if (c != null) {
- filterItem.setChecked(true);
- filterItem.setTitle(c.prettyPrint(getContext()));
- }
- }
- } else {
- CrashHandler.report(new Exception("Search menu not found"));
- }
-
- MenuItem groupingItem = menu.findItem(R.id.GROUPING_COMMAND);
- if (groupingItem != null) {
- SubMenu groupingMenu = groupingItem.getSubMenu();
- Utils.configureGroupingMenu(groupingMenu, mAccount.getGrouping());
- }
-
- MenuItem sortDirectionItem = menu.findItem(R.id.SORT_DIRECTION_COMMAND);
- if (sortDirectionItem != null) {
- SubMenu sortDirectionMenu = sortDirectionItem.getSubMenu();
- Utils.configureSortDirectionMenu(sortDirectionMenu, mAccount.getSortDirection());
- }
-
- MenuItem balanceItem = menu.findItem(R.id.BALANCE_COMMAND);
- if (balanceItem != null) {
- Utils.menuItemSetEnabledAndVisible(balanceItem, mAccount.getType() != AccountType.CASH && !mAccount.isSealed());
- }
-
- MenuItem syncItem = menu.findItem(R.id.SYNC_COMMAND);
- if (syncItem != null) {
- Utils.menuItemSetEnabledAndVisible(syncItem, mAccount.getSyncAccountName() != null);
- }
- }
-
- @Override
- public void onSaveInstanceState(@NonNull Bundle outState) {
- super.onSaveInstanceState(outState);
- if (filterPersistence != null) {
- filterPersistence.onSaveInstanceState(outState);
- }
- Icepick.saveInstanceState(this, outState);
- }
-
-/* public ArrayList> getFilterCriteria() {
- return getFilter().getCriteria();
- }*/
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- if (resultCode == Activity.RESULT_CANCELED) {
- return;
- }
- if (requestCode == FILTER_PAYEE_REQUEST) {
- String label = intent.getStringExtra(KEY_LABEL);
- if (resultCode == Activity.RESULT_OK) {
- long payeeId = intent.getLongExtra(KEY_ROWID, 0);
- addPayeeFilter(label, payeeId);
- }
- if (resultCode == Activity.RESULT_FIRST_USER) {
- long[] payeeIds = intent.getLongArrayExtra(KEY_ROWID);
- addPayeeFilter(label, payeeIds);
- }
- }
- if (requestCode == FILTER_CATEGORY_REQUEST) {
- String label = intent.getStringExtra(KEY_LABEL);
- if (resultCode == Activity.RESULT_OK) {
- long catId = intent.getLongExtra(KEY_ROWID, 0);
- addCategoryFilter(label, catId);
- }
- if (resultCode == Activity.RESULT_FIRST_USER) {
- long[] catIds = intent.getLongArrayExtra(KEY_CATID);
- addCategoryFilter(label, catIds);
- }
- } else if (requestCode == FILTER_TAGS_REQUEST) {
- final ArrayList tagList = intent.getParcelableArrayListExtra(KEY_TAG_LIST);
- if (tagList != null && !tagList.isEmpty()) {
- long[] tagIds = Stream.of(tagList).mapToLong(Tag::getId).toArray();
- String label = Stream.of(tagList).map(Tag::getLabel).collect(Collectors.joining(", "));
- addFilterCriteria(new TagCriterion(label, tagIds));
- }
- } else if (false/*requestCode == MAP_CATEGORY_REQUEST || requestCode == MAP_PAYEE_REQUEST
- || requestCode == MAP_METHOD_REQUEST || requestCode == MAP_ACCOUNT_REQUEST*/) {
- /* Bundle b = new Bundle();
- int columnStringResId, confirmationStringResId;
- String column;
- String intentKey = KEY_ROWID;
- switch (requestCode) {
- case MAP_CATEGORY_REQUEST: {
- column = intentKey = KEY_CATID;
- columnStringResId = R.string.category;
- confirmationStringResId = R.string.remap_category;
- break;
- }
- case MAP_PAYEE_REQUEST: {
- column = intentKey = KEY_PAYEEID;
- columnStringResId = R.string.payer_or_payee;
- confirmationStringResId = R.string.remap_payee;
- break;
- }
- case MAP_METHOD_REQUEST: {
- column = KEY_METHODID;
- columnStringResId = R.string.method;
- confirmationStringResId = R.string.remap_method;
- break;
- }
- case MAP_ACCOUNT_REQUEST: {
- column = KEY_ACCOUNTID;
- columnStringResId = R.string.account;
- confirmationStringResId = R.string.remap_account;
- break;
- }
- default:
- throw new IllegalStateException("Unexpected value: " + requestCode);
- }
- b.putString(KEY_COLUMN, column);
- b.putLong(KEY_ROWID, intent.getLongExtra(intentKey, 0));
- b.putString(KEY_TITLE_STRING, getString(R.string.dialog_title_confirm_remap, getString(columnStringResId)));
- b.putInt(KEY_POSITIVE_BUTTON_LABEL, R.string.menu_remap);
- b.putInt(ConfirmationDialogFragment.KEY_POSITIVE_BUTTON_CHECKED_LABEL, R.string.button_label_clone_and_remap);
- b.putInt(ConfirmationDialogFragment.KEY_NEGATIVE_BUTTON_LABEL, android.R.string.cancel);
- b.putString(KEY_MESSAGE, getString(confirmationStringResId, intent.getStringExtra(KEY_LABEL)) + " " + getString(R.string.continue_confirmation));
- b.putString(ConfirmationDialogFragment.KEY_CHECKBOX_LABEL, getString(R.string.menu_clone_transaction));
- b.putInt(KEY_COMMAND_POSITIVE, R.id.REMAP_COMMAND);
- showConfirmationDialog(b, REMAP_DIALOG);
- */
- }
- }
-
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
- if (key.equals(String.format(Locale.ROOT, prefNameForCriteria(), KEY_PAYEEID))) {
- filterPersistence = new FilterPersistence(prefHandler, prefNameForCriteria(), null, true, true);
- refreshAfterFilterChange();
- }
- }
-
- @Override
- public boolean onResult(@NonNull String dialogTag, int which, @NonNull Bundle extras) {
- if (which == BUTTON_POSITIVE) {
- if (NEW_TEMPLATE_DIALOG.equals(dialogTag)) {
- MyExpenses ctx = (MyExpenses) requireActivity();
- String label = extras.getString(SimpleInputDialog.TEXT);
- final Transaction transaction = Transaction.getInstanceFromDb(extras.getLong(KEY_ROWID));
- Uri uri = transaction == null ? null : new Template(transaction, label).save();
- if (uri == null) {
- //ctx.showSnackBar(R.string.template_create_error);
- } else {
- // show template edit activity
- Intent i = new Intent(ctx, ExpenseEdit.class);
- i.putExtra(DatabaseConstants.KEY_TEMPLATEID, ContentUris.parseId(uri));
- startActivity(i);
- }
- finishActionMode();
- }
- if (BaseTransactionList.FILTER_COMMENT_DIALOG.equals(dialogTag)) {
- final String textResult = extras.getString(SimpleInputDialog.TEXT);
- if (textResult != null) {
- addFilterCriteria(
- new CommentCriterion(textResult.trim()));
- }
- return true;
- }
- return true;
- }
- return false;
- }
-
- public void remap(@NonNull Bundle extras, boolean shouldClone) {
- final long[] checkedItemIds = binding.list.getCheckedItemIds();
- final String column = extras.getString(KEY_COLUMN);
- if (column == null) return;
- if (shouldClone) {
- final ProgressDialogFragment progressDialog = ProgressDialogFragment.newInstance(
- getString(R.string.saving), null, ProgressDialog.STYLE_HORIZONTAL, false);
- progressDialog.setMax(checkedItemIds.length);
- getParentFragmentManager()
- .beginTransaction()
- .add(progressDialog, PROGRESS_TAG)
- .commit();
- viewModel.cloneAndRemap(checkedItemIds, column, extras.getLong(KEY_ROWID));
- } else {
- viewModel.remap(checkedItemIds, column, extras.getLong(KEY_ROWID))
- .observe(this, result -> {
- final String message = result > 0 ? getString(R.string.remapping_result) : "No transactions were mapped";
- ((ProtectedFragmentActivity) requireActivity()).showSnackBar(message);
- });
- }
- }
-
- private void addCategoryFilter(String label, long... catIds) {
- addFilterCriteria(catIds.length == 1 && catIds[0] == NULL_ITEM_ID ?
- new CategoryCriterion() : new CategoryCriterion(label, catIds));
- }
-
- private void addPayeeFilter(String label, long... payeeIds) {
- addFilterCriteria(payeeIds.length == 1 && payeeIds[0] == NULL_ITEM_ID ?
- new PayeeCriterion() : new PayeeCriterion(label, payeeIds));
- }
-
-}
diff --git a/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/ConfirmTagDialogFragment.kt b/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/ConfirmTagDialogFragment.kt
index 7c31ee18bc..adaee8ab2f 100644
--- a/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/ConfirmTagDialogFragment.kt
+++ b/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/ConfirmTagDialogFragment.kt
@@ -7,6 +7,7 @@ import androidx.fragment.app.setFragmentResult
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.list.listItemsSingleChoice
import org.totschnig.myexpenses.R
+import org.totschnig.myexpenses.activity.TagHandler
import org.totschnig.myexpenses.activity.TagHandler.Companion.CONFIRM_MAP_TAG_REQUEST
import org.totschnig.myexpenses.viewmodel.data.Tag
@@ -34,7 +35,7 @@ class ConfirmTagDialogFragment : DialogFragment() {
private fun confirm(replace: Boolean) {
setFragmentResult(CONFIRM_MAP_TAG_REQUEST, Bundle(2).apply {
- putBoolean(KEY_REPLACE, replace)
+ putBoolean(TagHandler.KEY_REPLACE, replace)
putParcelableArrayList(KEY_TAG_LIST, tagList)
})
}
diff --git a/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/TransactionList.kt b/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/TransactionList.kt
deleted file mode 100644
index d13abc4800..0000000000
--- a/myExpenses/src/main/java/org/totschnig/myexpenses/fragment/TransactionList.kt
+++ /dev/null
@@ -1,635 +0,0 @@
-package org.totschnig.myexpenses.fragment
-
-import android.content.Intent
-import android.os.Bundle
-import android.text.TextUtils
-import android.util.SparseBooleanArray
-import android.view.ActionMode
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import android.widget.AbsListView
-import androidx.lifecycle.lifecycleScope
-import eltos.simpledialogfragment.input.SimpleInputDialog
-import icepick.State
-import org.totschnig.myexpenses.ACTION_SELECT_FILTER
-import org.totschnig.myexpenses.ACTION_SELECT_MAPPING
-import org.totschnig.myexpenses.R
-import org.totschnig.myexpenses.activity.*
-import org.totschnig.myexpenses.dialog.AmountFilterDialog
-import org.totschnig.myexpenses.dialog.ConfirmationDialogFragment
-import org.totschnig.myexpenses.dialog.DateFilterDialog
-import org.totschnig.myexpenses.dialog.TransactionDetailFragment
-import org.totschnig.myexpenses.dialog.select.*
-import org.totschnig.myexpenses.dialog.select.SelectMultipleAccountDialogFragment.Companion.newInstance
-import org.totschnig.myexpenses.model.ContribFeature
-import org.totschnig.myexpenses.model.CrStatus
-import org.totschnig.myexpenses.provider.CheckTransferAccountOfSplitPartsHandler
-import org.totschnig.myexpenses.provider.DatabaseConstants
-import org.totschnig.myexpenses.provider.DatabaseConstants.KEY_AMOUNT
-import org.totschnig.myexpenses.provider.DatabaseConstants.KEY_IS_SAME_CURRENCY
-import org.totschnig.myexpenses.provider.DbUtils
-import org.totschnig.myexpenses.task.TaskExecutionFragment
-import org.totschnig.myexpenses.util.*
-import org.totschnig.myexpenses.util.TextUtils.concatResStrings
-import org.totschnig.myexpenses.util.TextUtils.withAmountColor
-import org.totschnig.myexpenses.util.crashreporting.CrashHandler
-import org.totschnig.myexpenses.viewmodel.KEY_ROW_IDS
-import se.emilsjolander.stickylistheaders.StickyListHeadersListView
-import kotlin.math.sign
-
-const val KEY_REPLACE = "replace"
-
-class TransactionList : BaseTransactionList() {
-
- @JvmField
- @State
- var selectedTransactionSum: Long = 0
-
- @JvmField
- @State
- var selectedTransactionSumFormatted: String? = null
-/*
- private fun handleTagResult(intent: Intent) {
- lifecycleScope.launchWhenResumed {
- ConfirmTagDialogFragment().also {
- it.arguments = Bundle().apply {
- putParcelableArrayList(
- KEY_TAG_LIST,
- intent.getParcelableArrayListExtra(KEY_TAG_LIST)
- )
- }
- it.setTargetFragment(this@TransactionList, CONFIRM_MAP_TAG_REQUEST)
- }.show(parentFragmentManager, "CONFIRM")
- }
- }*/
-
-/* override fun onActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) {
- if (resultCode != Activity.RESULT_CANCELED) {
- when (requestCode) {
- CONFIRM_MAP_TAG_REQUEST -> {
- intent?.let {
- viewModel.tag(
- binding.list.checkedItemIds,
- it.getParcelableArrayListExtra(KEY_TAG_LIST)!!,
- it.getBooleanExtra(KEY_REPLACE, false)
- )
- }
- finishActionMode()
- }
- MAP_TAG_REQUEST -> {
- handleTagResult(intent!!)
- }
- else -> {
- super.onActivityResult(requestCode, resultCode, intent)
- }
- }
- }
- }*/
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (mAccount == null || activity == null) {
- return false
- }
- when (val command = item.itemId) {
- R.id.FILTER_CATEGORY_COMMAND -> {
- if (!removeFilter(command)) {
- val i = Intent(activity, ManageCategories::class.java)
- i.action = ACTION_SELECT_FILTER
- startActivityForResult(i, FILTER_CATEGORY_REQUEST)
- }
- return true
- }
- R.id.FILTER_TAG_COMMAND -> {
- if (!removeFilter(command)) {
- val i = Intent(activity, ManageTags::class.java)
- i.action = ACTION_SELECT_FILTER
- startActivityForResult(i, FILTER_TAGS_REQUEST)
- }
- return true
- }
- R.id.FILTER_AMOUNT_COMMAND -> {
- if (!removeFilter(command)) {
- AmountFilterDialog.newInstance(mAccount.currencyUnit)
- .show(requireActivity().supportFragmentManager, "AMOUNT_FILTER")
- }
- return true
- }
- R.id.FILTER_DATE_COMMAND -> {
- if (!removeFilter(command)) {
- DateFilterDialog.newInstance()
- .show(requireActivity().supportFragmentManager, "DATE_FILTER")
- }
- return true
- }
- R.id.FILTER_COMMENT_COMMAND -> {
- if (!removeFilter(command)) {
- SimpleInputDialog.build()
- .title(R.string.search_comment)
- .pos(R.string.menu_search)
- .neut()
- .show(this, FILTER_COMMENT_DIALOG)
- }
- return true
- }
- R.id.FILTER_STATUS_COMMAND -> {
- if (!removeFilter(command)) {
- SelectCrStatusDialogFragment.newInstance()
- .show(requireActivity().supportFragmentManager, "STATUS_FILTER")
- }
- return true
- }
- R.id.FILTER_PAYEE_COMMAND -> {
- if (!removeFilter(command)) {
- val i = Intent(activity, ManageParties::class.java)
- i.action = ACTION_SELECT_FILTER
- i.putExtra(DatabaseConstants.KEY_ACCOUNTID, mAccount.id)
- startActivityForResult(i, FILTER_PAYEE_REQUEST)
- }
- return true
- }
- R.id.FILTER_METHOD_COMMAND -> {
- if (!removeFilter(command)) {
- SelectMethodDialogFragment.newInstance(mAccount.id)
- .show(requireActivity().supportFragmentManager, "METHOD_FILTER")
- }
- return true
- }
- R.id.FILTER_TRANSFER_COMMAND -> {
- if (!removeFilter(command)) {
- SelectTransferAccountDialogFragment.newInstance(mAccount.id)
- .show(requireActivity().supportFragmentManager, "TRANSFER_FILTER")
- }
- return true
- }
- R.id.FILTER_ACCOUNT_COMMAND -> {
- if (!removeFilter(command)) {
- newInstance(mAccount.currencyUnit.code)
- .show(requireActivity().supportFragmentManager, "ACCOUNT_FILTER")
- }
- return true
- }
- R.id.PRINT_COMMAND -> {
- val ctx = requireActivity() as MyExpenses
- if (hasItems) {
- AppDirHelper.checkAppDir(requireContext()).onSuccess {
- ctx.contribFeatureRequested(ContribFeature.PRINT, null)
- }.onFailure {
- ctx.showDismissibleSnackBar(it.safeMessage)
- }
- } else {
- ctx.showExportDisabledCommand()
- }
- return true
- }
- R.id.SYNC_COMMAND -> {
- //mAccount.requestSync()
- return true
- }
- else -> return super.onOptionsItemSelected(item)
- }
- }
-
- override fun onHeaderLongClick(
- l: StickyListHeadersListView?, header: View?,
- itemPosition: Int, headerId: Long, currentlySticky: Boolean
- ): Boolean {
- val ctx = requireActivity() as MyExpenses
- headerData?.get(headerId)?.get(6)?.let {
- if (it > 0) {
- ctx.contribFeatureRequested(ContribFeature.DISTRIBUTION, headerId.toInt())
- } else {
- ctx.showSnackBar(R.string.no_mapped_transactions)
- }
- }
- return true
- }
-
- private fun warnSealedAccount(sealedAccount: Boolean, sealedDebt: Boolean, multiple: Boolean) {
- val resIds = mutableListOf()
- if (multiple) {
- resIds.add(R.string.warning_account_for_transaction_is_closed)
- }
- if (sealedAccount) {
- resIds.add(R.string.object_sealed)
- }
- if (sealedDebt) {
- resIds.add(R.string.object_sealed_debt)
- }
- (requireActivity() as ProtectedFragmentActivity).showSnackBar(
- concatResStrings(
- requireContext(),
- " ",
- *resIds.toIntArray()
- )
- )
- }
-
- override fun checkSealed(itemIds: LongArray, onChecked: Runnable) {
- /* (requireActivity() as BaseMyExpenses).buildCheckSealedHandler().check(itemIds) { result ->
- lifecycleScope.launchWhenResumed {
- result.onSuccess {
- if (it.first && it.second) {
- onChecked.run()
- } else {
- warnSealedAccount(!it.first, !it.second, itemIds.size > 1)
- }
- }.onFailure(showFailure)
- }
- }*/
- }
-
- val showFailure: (exception: Throwable) -> Unit = {
- (requireActivity() as ProtectedFragmentActivity).showSnackBar(it.message!!)
- }
-
- override fun dispatchCommandMultiple(
- command: Int,
- positions: SparseBooleanArray,
- itemIds: LongArray
- ): Boolean {
- if (super.dispatchCommandMultiple(command, positions, itemIds)) {
- return true
- }
- val ctx = activity as MyExpenses? ?: return false
- if (command == R.id.DELETE_COMMAND) {
- var hasReconciled = false
- var hasNotVoid = false
- for (i in 0 until positions.size()) {
- if (positions.valueAt(i)) {
- val pos = positions.keyAt(i)
- if (mTransactionsCursor.moveToPosition(pos)) {
- val status = enumValueOrDefault(
- mTransactionsCursor.getString(columnIndexCrStatus),
- CrStatus.UNRECONCILED
- )
- if (status == CrStatus.RECONCILED) {
- hasReconciled = true
- }
- if (status != CrStatus.VOID) {
- hasNotVoid = true
- }
- if (hasNotVoid && hasReconciled) break
- } else {
- CrashHandler.report(IllegalStateException("Move to position $pos failed (count = ${mTransactionsCursor.count}"))
- return true
- }
- }
- }
- val finalHasReconciled = hasReconciled
- val finalHasNotVoid = hasNotVoid
- checkSealed(itemIds) {
- var message = resources.getQuantityString(
- R.plurals.warning_delete_transaction,
- itemIds.size,
- itemIds.size
- )
- if (finalHasReconciled) {
- message += " " + getString(R.string.warning_delete_reconciled)
- }
- val b = Bundle()
- b.putInt(
- ConfirmationDialogFragment.KEY_TITLE,
- R.string.dialog_title_warning_delete_transaction
- )
- b.putString(ConfirmationDialogFragment.KEY_MESSAGE, message)
- b.putInt(ConfirmationDialogFragment.KEY_COMMAND_POSITIVE, R.id.DELETE_COMMAND_DO)
- b.putInt(
- ConfirmationDialogFragment.KEY_COMMAND_NEGATIVE,
- R.id.CANCEL_CALLBACK_COMMAND
- )
- b.putInt(ConfirmationDialogFragment.KEY_POSITIVE_BUTTON_LABEL, R.string.menu_delete)
- if (finalHasNotVoid) {
- b.putString(
- ConfirmationDialogFragment.KEY_CHECKBOX_LABEL,
- getString(R.string.mark_void_instead_of_delete)
- )
- }
- b.putLongArray(KEY_ROW_IDS, itemIds)
- showConfirmationDialog(b, "DELETE_TRANSACTION")
- }
- return true
- } else if (command == R.id.SPLIT_TRANSACTION_COMMAND) {
- checkSealed(itemIds) {
- ctx.contribFeatureRequested(
- ContribFeature.SPLIT_TRANSACTION,
- itemIds
- )
- }
- } else if (command == R.id.UNGROUP_SPLIT_COMMAND) {
- checkSealed(itemIds) {
- val b = Bundle()
- b.putString(
- ConfirmationDialogFragment.KEY_MESSAGE,
- getString(R.string.warning_ungroup_split_transactions)
- )
- b.putInt(
- ConfirmationDialogFragment.KEY_COMMAND_POSITIVE,
- R.id.UNGROUP_SPLIT_COMMAND
- )
- b.putInt(
- ConfirmationDialogFragment.KEY_COMMAND_NEGATIVE,
- R.id.CANCEL_CALLBACK_COMMAND
- )
- b.putInt(
- ConfirmationDialogFragment.KEY_POSITIVE_BUTTON_LABEL,
- R.string.menu_ungroup_split_transaction
- )
- b.putLongArray(TaskExecutionFragment.KEY_LONG_IDS, itemIds)
- showConfirmationDialog(b, "UNSPLIT_TRANSACTION")
- }
- return true
- } else if (command == R.id.UNDELETE_COMMAND) {
- checkSealed(itemIds) {
- viewModel.undeleteTransactions(itemIds).observe(
- viewLifecycleOwner
- ) { result: Int ->
- if (result == 0) (requireActivity() as BaseActivity)
- .showDeleteFailureFeedback(null)
- }
- }
- } else if (command == R.id.REMAP_CATEGORY_COMMAND) {
- checkSealed(itemIds) {
- val i = Intent(activity, ManageCategories::class.java)
- i.action = ACTION_SELECT_MAPPING
- //startActivityForResult(i, MAP_CATEGORY_REQUEST)
- }
- return true
- } else if (command == R.id.MAP_TAG_COMMAND) {
- checkSealed(itemIds) {
- val i = Intent(activity, ManageTags::class.java)
- i.action = ACTION_SELECT_MAPPING
- //startActivityForResult(i, MAP_TAG_REQUEST)
- }
- return true
- } else if (command == R.id.REMAP_PAYEE_COMMAND) {
- checkSealed(itemIds) {
- val i = Intent(activity, ManageParties::class.java)
- i.action = ACTION_SELECT_MAPPING
- //startActivityForResult(i, MAP_PAYEE_REQUEST)
- }
- return true
- } else if (command == R.id.REMAP_METHOD_COMMAND) {
- checkSealed(itemIds) {
- var hasExpense = false
- var hasIncome = false
- val accountTypes: MutableSet = HashSet()
- for (i in 0 until positions.size()) {
- if (positions.valueAt(i)) {
- mTransactionsCursor.moveToPosition(positions.keyAt(i))
- val amount = mTransactionsCursor.getLong(
- mTransactionsCursor.getColumnIndexOrThrow(KEY_AMOUNT)
- )
- if (amount > 0) hasIncome = true
- if (amount < 0) hasExpense = true
- accountTypes.add(
- mTransactionsCursor.getString(
- mTransactionsCursor.getColumnIndexOrThrow(
- DatabaseConstants.KEY_ACCOUNT_TYPE
- )
- )
- )
- }
- }
- var type = 0
- if (hasExpense && !hasIncome) type = -1 else if (hasIncome && !hasExpense) type = 1
- lifecycleScope.launchWhenResumed {
- val dialogFragment = SelectSingleMethodDialogFragment.newInstance(
- R.string.menu_remap,
- R.string.remap_empty_list,
- accountTypes.toTypedArray(),
- type
- )
- //dialogFragment.setTargetFragment(this@TransactionList, MAP_METHOD_REQUEST)
- dialogFragment.show(requireActivity().supportFragmentManager, "REMAP_METHOD")
- }
- }
- return true
- } else if (command == R.id.REMAP_ACCOUNT_COMMAND) {
- checkSealed(itemIds) {
- val excludedIds: MutableList = ArrayList()
- val splitIds: MutableList = ArrayList()
- if (!mAccount.isAggregate) {
- excludedIds.add(mAccount.id)
- }
- for (i in 0 until positions.size()) {
- if (positions.valueAt(i)) {
- mTransactionsCursor.moveToPosition(positions.keyAt(i))
- val transferAccount = DbUtils.getLongOr0L(
- mTransactionsCursor,
- DatabaseConstants.KEY_TRANSFER_ACCOUNT
- )
- if (transferAccount != 0L) {
- excludedIds.add(transferAccount)
- }
- if (DatabaseConstants.SPLIT_CATID == DbUtils.getLongOrNull(
- mTransactionsCursor,
- DatabaseConstants.KEY_CATID
- )
- ) {
- splitIds.add(
- DbUtils.getLongOr0L(
- mTransactionsCursor,
- DatabaseConstants.KEY_ROWID
- )
- )
- }
- }
- }
- CheckTransferAccountOfSplitPartsHandler(requireActivity().contentResolver).check(
- splitIds
- ) { result ->
- lifecycleScope.launchWhenResumed {
- result.onSuccess {
- excludedIds.addAll(it)
- val dialogFragment =
- SelectSingleAccountDialogFragment.newInstance(
- R.string.menu_remap,
- R.string.remap_empty_list,
- excludedIds
- )
-/* dialogFragment.setTargetFragment(
- this@TransactionList,
- MAP_ACCOUNT_REQUEST
- )*/
- dialogFragment.show(
- requireActivity().supportFragmentManager,
- "REMAP_ACCOUNT"
- )
- }.onFailure(showFailure)
- }
- }
- }
- return true
- } else if (command == R.id.LINK_TRANSFER_COMMAND) {
- checkSealed(itemIds) {
- val b = Bundle()
- b.putString(
- ConfirmationDialogFragment.KEY_MESSAGE,
- getString(R.string.warning_link_transfer) + " " + getString(R.string.continue_confirmation)
- )
- b.putInt(
- ConfirmationDialogFragment.KEY_COMMAND_POSITIVE,
- R.id.LINK_TRANSFER_COMMAND
- )
- b.putInt(
- ConfirmationDialogFragment.KEY_COMMAND_NEGATIVE,
- R.id.CANCEL_CALLBACK_COMMAND
- )
- b.putInt(
- ConfirmationDialogFragment.KEY_POSITIVE_BUTTON_LABEL,
- R.string.menu_create_transfer
- )
- b.putLongArray(KEY_ROW_IDS, itemIds)
- showConfirmationDialog(b, "LINK_TRANSFER")
- }
- return true
- }
- return false
- }
-
- override fun onFinishActionMode() {
- super.onFinishActionMode()
- selectedTransactionSum = 0
- }
-
- override fun setTitle(mode: ActionMode, lv: AbsListView) {
- val count = lv.checkedItemCount
- if (count > 1) {
- mAccount?.let {
- selectedTransactionSumFormatted =
- currencyFormatter.convAmount(selectedTransactionSum, it.currencyUnit)
- }
- mode.title = TextUtils.concat(
- count.toString(), " ", setColor(selectedTransactionSumFormatted)
- )
- } else {
- super.setTitle(mode, lv)
- }
- }
-
- private fun setColor(text: String?) =
- text?.withAmountColor(resources, selectedTransactionSum.sign) ?: ""
-
- override fun onSelectionChanged(position: Int, checked: Boolean) {
- if (mTransactionsCursor.moveToPosition(position)) {
- val amount =
- mTransactionsCursor.getLong(mTransactionsCursor.getColumnIndexOrThrow(KEY_AMOUNT))
- val shouldCount = if (isTransferAtPosition(position) && mAccount.isAggregate) {
- if (mAccount.isHomeAggregate) false else mTransactionsCursor.getInt(
- mTransactionsCursor.getColumnIndexOrThrow(KEY_IS_SAME_CURRENCY)
- ) != 1
- } else true
- if (shouldCount) {
- if (checked) {
- selectedTransactionSum += amount
- } else {
- selectedTransactionSum -= amount
- }
- }
- }
- }
-
-
- override fun configureMenu(menu: Menu, lv: AbsListView) {
- super.configureMenu(menu, lv)
- val checkedItemPositions = lv.checkedItemPositions
- var hasSplit = false
- var hasVoid = false
- var hasNotSplit = false
- var hasTransfer = false
- var canLinkAsTransfer = false
- for (i in 0 until checkedItemPositions.size()) {
- if (checkedItemPositions.valueAt(i)) {
- if (isSplitAtPosition(checkedItemPositions.keyAt(i))) {
- hasSplit = true
- } else {
- hasNotSplit = true
- }
- if (hasSplit && hasNotSplit) {
- break
- }
- }
- }
- for (i in 0 until checkedItemPositions.size()) {
- if (checkedItemPositions.valueAt(i)) {
- if (isVoidAtPosition(checkedItemPositions.keyAt(i))) {
- hasVoid = true
- break
- }
- }
- }
- for (i in 0 until checkedItemPositions.size()) {
- if (checkedItemPositions.valueAt(i)) {
- if (isTransferAtPosition(checkedItemPositions.keyAt(i))) {
- hasTransfer = true
- break
- }
- }
- }
- if (lv.checkedItemCount == 2 && !hasSplit && !hasTransfer) {
- val checked = checkedItemPositions.asTrueSequence().toList()
- canLinkAsTransfer = checked.size == 2 && canLinkPositions(checked[0], checked[1])
- }
-
- with(menu) {
- findItem(R.id.CREATE_TEMPLATE_COMMAND).isVisible = lv.checkedItemCount == 1
- findItem(R.id.SPLIT_TRANSACTION_COMMAND).isVisible = !hasSplit && !hasVoid
- findItem(R.id.UNGROUP_SPLIT_COMMAND).isVisible = !hasNotSplit && !hasVoid
- findItem(R.id.UNDELETE_COMMAND).isVisible = hasVoid
- findItem(R.id.EDIT_COMMAND).isVisible = lv.checkedItemCount == 1 && !hasVoid
- findItem(R.id.REMAP_ACCOUNT_COMMAND).isVisible =
- ((activity as? MyExpenses)?.accountCount ?: 0) > 1
- findItem(R.id.REMAP_PAYEE_COMMAND).isVisible = !hasTransfer
- findItem(R.id.REMAP_CATEGORY_COMMAND).isVisible = !hasTransfer && !hasSplit
- findItem(R.id.REMAP_METHOD_COMMAND).isVisible = !hasTransfer
- findItem(R.id.LINK_TRANSFER_COMMAND).isVisible = canLinkAsTransfer
- }
- }
-
- private fun canLinkPositions(position1: Int, position2: Int): Boolean {
- if (mTransactionsCursor != null && columnIndexAccountId > -1) {
- if (mTransactionsCursor.moveToPosition(position1)) {
- val accountId1 = mTransactionsCursor.getLong(columnIndexAccountId)
- val amount1 = mTransactionsCursor.getLong(columnIndexAmount)
- val currency1 = currencyAtPosition
- if (mTransactionsCursor.moveToPosition(position2)) {
- //we either have two transactions with different currencies or with the same amount
- return accountId1 != mTransactionsCursor.getLong(columnIndexAccountId) &&
- (amount1 == -mTransactionsCursor.getLong(columnIndexAmount) || currency1 != currencyAtPosition)
- }
- }
- }
- return false
- }
-
- private val currencyAtPosition: String?
- get() = columnIndexCurrency.takeIf { it > -1 }?.let { mTransactionsCursor.getString(it) }
-
- override fun showDetails(transactionId: Long) {
- lifecycleScope.launchWhenResumed {
- with(parentFragmentManager) {
- if (findFragmentByTag(TransactionDetailFragment::class.java.name) == null) {
- TransactionDetailFragment.newInstance(transactionId)
- .show(this, TransactionDetailFragment::class.java.name)
- }
- }
- }
- }
-
- override fun showConfirmationDialog(bundle: Bundle?, tag: String?) {
- lifecycleScope.launchWhenResumed {
- ConfirmationDialogFragment.newInstance(bundle).show(parentFragmentManager, tag)
- }
- }
-
- /**
- * reimplement DbConstants.budgetColumn outside of Database
- */
- override fun resolveBudget(headerId: Int) =
- budgetAmounts?.takeIf { it.isNotEmpty() }?.let { budgetAmounts ->
- budgetAmounts.find { it.first == headerId } ?:
- budgetAmounts.lastOrNull { !it.third && it.first < headerId }
- }?.second
-}
-
diff --git a/myExpenses/src/main/java/org/totschnig/myexpenses/task/PrintTask.java b/myExpenses/src/main/java/org/totschnig/myexpenses/task/PrintTask.java
index e4c6b1bc55..f168c7698d 100644
--- a/myExpenses/src/main/java/org/totschnig/myexpenses/task/PrintTask.java
+++ b/myExpenses/src/main/java/org/totschnig/myexpenses/task/PrintTask.java
@@ -8,7 +8,6 @@
import org.totschnig.myexpenses.MyApplication;
import org.totschnig.myexpenses.R;
import org.totschnig.myexpenses.export.pdf.PdfPrinter;
-import org.totschnig.myexpenses.fragment.TransactionList;
import org.totschnig.myexpenses.model.Account;
import org.totschnig.myexpenses.provider.filter.WhereFilter;
import org.totschnig.myexpenses.ui.ContextHelper;
@@ -20,6 +19,7 @@
import static org.totschnig.myexpenses.provider.DatabaseConstants.KEY_CURRENT_BALANCE;
import static org.totschnig.myexpenses.provider.DatabaseConstants.KEY_ROWID;
+import static org.totschnig.myexpenses.provider.filter.FilterPersistenceKt.KEY_FILTER;
public class PrintTask extends AsyncTask> {
private final TaskExecutionFragment taskExecutionFragment;
@@ -30,7 +30,7 @@ public class PrintTask extends AsyncTask> {
PrintTask(TaskExecutionFragment taskExecutionFragment, Bundle extras) {
this.taskExecutionFragment = taskExecutionFragment;
accountId = extras.getLong(KEY_ROWID);
- filter = new WhereFilter(extras.getParcelableArrayList(TransactionList.KEY_FILTER));
+ filter = new WhereFilter(extras.getParcelableArrayList(KEY_FILTER));
currentBalance = extras.getLong(KEY_CURRENT_BALANCE);
}
diff --git a/myExpenses/src/main/java/org/totschnig/myexpenses/viewmodel/ExportViewModel.kt b/myExpenses/src/main/java/org/totschnig/myexpenses/viewmodel/ExportViewModel.kt
index e71591dd19..348a4968f2 100644
--- a/myExpenses/src/main/java/org/totschnig/myexpenses/viewmodel/ExportViewModel.kt
+++ b/myExpenses/src/main/java/org/totschnig/myexpenses/viewmodel/ExportViewModel.kt
@@ -5,11 +5,7 @@ import android.net.Uri
import android.os.Bundle
import androidx.lifecycle.liveData
import androidx.lifecycle.viewModelScope
-import kotlinx.coroutines.flow.MutableSharedFlow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharedFlow
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import org.totschnig.myexpenses.MyApplication
import org.totschnig.myexpenses.R
@@ -17,7 +13,6 @@ import org.totschnig.myexpenses.export.CsvExporter
import org.totschnig.myexpenses.export.JSONExporter
import org.totschnig.myexpenses.export.QifExporter
import org.totschnig.myexpenses.export.createFileFailure
-import org.totschnig.myexpenses.fragment.BaseTransactionList
import org.totschnig.myexpenses.model.Account
import org.totschnig.myexpenses.model.AggregateAccount
import org.totschnig.myexpenses.model.ExportFormat
@@ -26,6 +21,7 @@ import org.totschnig.myexpenses.preference.PrefKey
import org.totschnig.myexpenses.provider.DatabaseConstants
import org.totschnig.myexpenses.provider.DbUtils
import org.totschnig.myexpenses.provider.TransactionProvider
+import org.totschnig.myexpenses.provider.filter.KEY_FILTER
import org.totschnig.myexpenses.provider.filter.WhereFilter
import org.totschnig.myexpenses.ui.ContextHelper
import org.totschnig.myexpenses.util.AppDirHelper
@@ -74,7 +70,7 @@ class ExportViewModel(application: Application) : ContentResolvingAndroidViewMod
val encoding = args.getString(KEY_ENCODING)!!
val handleDelete = args.getInt(KEY_EXPORT_HANDLE_DELETED)
val filter =
- WhereFilter(args.getParcelableArrayList(BaseTransactionList.KEY_FILTER)!!)
+ WhereFilter(args.getParcelableArrayList(KEY_FILTER)!!)
val fileName = args.getString(KEY_FILE_NAME)!!
val delimiter = args.getChar(KEY_DELIMITER)
diff --git a/myExpenses/src/main/res/layout/expenses_list.xml b/myExpenses/src/main/res/layout/expenses_list.xml
deleted file mode 100755
index 6e5b086cc9..0000000000
--- a/myExpenses/src/main/res/layout/expenses_list.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/myExpenses/src/main/res/xml/project_dependencies.xml b/myExpenses/src/main/res/xml/project_dependencies.xml
index a68001ddd7..70948c11d2 100644
--- a/myExpenses/src/main/res/xml/project_dependencies.xml
+++ b/myExpenses/src/main/res/xml/project_dependencies.xml
@@ -6,11 +6,6 @@
https://launchpad.net/financisto
GPL v2.0
-
- StickyListHeaders
- http://emilsjolander.github.io/StickyListHeaders
- Apache License, Version 2.0
-
iText
http://itextpdf.com
diff --git a/project.properties b/project.properties
index 0352b92a15..57b0d843d5 100644
--- a/project.properties
+++ b/project.properties
@@ -9,11 +9,4 @@
# Indicates whether an apk should be generated for each density.
split.density=false
-# Project target.
-target=android-21
-#Proguard
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt
-proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-android.library.reference.1=appcompat
-android.library.reference.2=StickyListHeaders/library
-android.library.reference.3=MPAndroidChart/MPChartLib
+