com.odoo.addons.notes.Notes.java Source code

Java tutorial

Introduction

Here is the source code for com.odoo.addons.notes.Notes.java

Source

/**
 * Odoo, Open Source Management Solution
 * Copyright (C) 2012-today Odoo SA (<http:www.odoo.com>)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http:www.gnu.org/licenses/>
 *
 * Created on 25/2/15 6:30 PM
 */
package com.odoo.addons.notes;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
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.widget.ImageView;
import android.widget.ListView;
import android.widget.Toast;

import com.odoo.R;
import com.odoo.addons.notes.dialogs.NoteColorDialog;
import com.odoo.addons.notes.dialogs.NoteStagesDialog;
import com.odoo.addons.notes.models.NoteNote;
import com.odoo.addons.notes.utils.NoteUtil;
import com.odoo.addons.notes.widgets.NotesWidget;
import com.odoo.addons.notes.widgets.WidgetHelper;
import com.odoo.base.addons.config.BaseConfigSettings;
import com.odoo.core.orm.ODataRow;
import com.odoo.core.orm.OValues;
import com.odoo.core.orm.fields.OColumn;
import com.odoo.core.support.addons.fragment.BaseFragment;
import com.odoo.core.support.addons.fragment.IOnSearchViewChangeListener;
import com.odoo.core.support.addons.fragment.ISyncStatusObserverListener;
import com.odoo.core.support.drawer.ODrawerItem;
import com.odoo.core.support.list.IOnItemClickListener;
import com.odoo.core.support.list.OCursorListAdapter;
import com.odoo.core.utils.IntentUtils;
import com.odoo.core.utils.OAlert;
import com.odoo.core.utils.OControls;
import com.odoo.core.utils.OCursorUtils;
import com.odoo.core.utils.ODateUtils;
import com.odoo.core.utils.StringUtils;
import com.odoo.core.utils.sys.IOnBackPressListener;
import com.odoo.widgets.bottomsheet.BottomSheet;
import com.odoo.widgets.bottomsheet.BottomSheetListeners;
import com.odoo.widgets.snackbar.SnackBar;
import com.odoo.widgets.snackbar.SnackbarBuilder;
import com.odoo.widgets.snackbar.listeners.ActionClickListener;
import com.odoo.widgets.snackbar.listeners.EventListener;

import java.util.ArrayList;
import java.util.List;

public class Notes extends BaseFragment
        implements ISyncStatusObserverListener, SwipeRefreshLayout.OnRefreshListener,
        LoaderManager.LoaderCallbacks<Cursor>, OCursorListAdapter.OnViewBindListener, IOnSearchViewChangeListener,
        View.OnClickListener, IOnItemClickListener, BottomSheetListeners.OnSheetItemClickListener,
        BottomSheetListeners.OnSheetActionClickListener, IOnBackPressListener,
        BottomSheetListeners.OnSheetMenuCreateListener, EventListener {
    public static final String TAG = Notes.class.getSimpleName();
    public static final String KEY_STAGE_ID = "stage_id";
    public static final String KEY_NOTE_ID = "note_id";
    public static final String KEY_NOTE_FILTER = "note_filter";
    private Type mCurrentKey = Type.Notes;
    private int mStageId = 0;
    private OCursorListAdapter mAdapter = null;
    private ListView mList = null;
    private View mView;
    private String mFilter = null;
    private BottomSheet mSheet;
    private Bundle extra;

    public enum Type {
        Notes, Archive, Reminders, Deleted, TagFilter
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.notes_listview, container, false);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mView = view;
        extra = getArguments();
        if (extra != null) {
            if (extra.containsKey(KEY_STAGE_ID)) {
                mStageId = extra.getInt(KEY_STAGE_ID);
                parent().setHasActionBarSpinner(true);
            }
            if (extra.containsKey(WidgetHelper.EXTRA_WIDGET_ITEM_KEY)) {
                Bundle data = new Bundle();
                data.putInt(KEY_STAGE_ID, mStageId);
                if (extra.getString(WidgetHelper.EXTRA_WIDGET_ITEM_KEY).equals(NotesWidget.KEY_NOTE_COMPOSE))
                    quickCreateNote(data);
                if (extra.getString(WidgetHelper.EXTRA_WIDGET_ITEM_KEY)
                        .equals(NotesWidget.KEY_NOTE_VOICE_TO_TEXT)) {
                    data.putString("type", "speechToText");
                    quickCreateNote(data);
                }

            }
        }
        setHasOptionsMenu(true);
        setHasSwipeRefreshView(view, R.id.swipe_container, this);
        setHasSyncStatusObserver(TAG, this, db());
        initAdapter();

        if (BaseConfigSettings.padInstalled(getActivity())) {
            OAlert.showWarning(getActivity(), "Pad installed. Unable to work offline.");
        }
    }

    private void initAdapter() {
        if (getActivity() != null) {
            mCurrentKey = Type.valueOf(getArguments().getString(KEY_NOTE_FILTER));
            if (mCurrentKey == Type.Deleted)
                mView.findViewById(R.id.fabButton).setVisibility(View.GONE);
            mList = (ListView) mView.findViewById(R.id.gridView);
            setHasFloatingButton(mView, R.id.fabButton, mList, this);
            //setHeaderView();
            mAdapter = new OCursorListAdapter(getActivity(), null, R.layout.note_custom_view_note);
            mAdapter.setOnViewBindListener(this);
            mList.setAdapter(mAdapter);
            mAdapter.handleItemClickListener(mList, this);
            getLoaderManager().initLoader(0, null, this);
        }
    }

    @Override
    public void onItemDoubleClick(View view, int position) {
        Cursor cr = (Cursor) mAdapter.getItem(position);
        Bundle bundle = new Bundle();
        bundle.putInt(KEY_NOTE_ID, cr.getInt(cr.getColumnIndex(OColumn.ROW_ID)));
        Intent intent = new Intent(getActivity(), NoteDetail.class);
        intent.putExtras(bundle);
        startActivity(intent);
    }

    @Override
    public void onItemClick(View view, int position) {
        Cursor cr = (Cursor) mAdapter.getItem(position);
        showSheet(cr);
    }

    private void showSheet(Cursor cr) {
        ODataRow data = OCursorUtils.toDatarow(cr);
        if (mSheet != null) {
            mSheet.dismiss();
        }
        BottomSheet.Builder builder = new BottomSheet.Builder(getActivity());
        builder.listener(this);
        builder.setIconColor(_c(R.color.body_text_2));
        builder.setTextColor(_c(R.color.body_text_1));
        builder.setData(cr);
        builder.actionListener(this);
        builder.setActionIcon(R.drawable.ic_action_edit);
        builder.title(data.getString("short_memo"));
        builder.setOnSheetMenuCreateListener(this);
        builder.menu(R.menu.menu_note_sheet);
        mSheet = builder.create();
        mSheet.show();
    }

    @Override
    public void onSheetMenuCreate(Menu menu, Object o) {
        if (mCurrentKey == Type.Deleted) {
            menu.findItem(R.id.menu_note_delete).setVisible(false);
        }
        if (mCurrentKey == Type.Archive || mCurrentKey == Type.Deleted) {
            menu.findItem(R.id.menu_note_archive).setIcon(R.drawable.ic_action_unarchive);
            menu.findItem(R.id.menu_note_archive).setTitle(R.string.label_unarchive);
        }
    }

    /**
     * Bottom Sheet click listener
     *
     * @param bottomSheet
     * @param menuItem
     * @param obj
     */
    @Override
    public void onItemClick(BottomSheet bottomSheet, MenuItem menuItem, Object obj) {
        ODataRow row = OCursorUtils.toDatarow((Cursor) obj);
        int row_id = row.getInt(OColumn.ROW_ID);
        switch (menuItem.getItemId()) {
        case R.id.menu_note_choose_color:
            chooseColor(row_id, row);
            break;
        case R.id.menu_note_archive:
            String open = (row.getString("open").equals("false")) ? "true" : "false";
            showArchiveUndoBar(row_id, open, row.getString("trashed").equals("1"));
            break;
        case R.id.menu_note_delete:
            int trashed = (row.getInt("trashed") == 1) ? 0 : 1;
            showTrashUndoBar(row_id, trashed);
            break;
        }
        bottomSheet.dismiss();
    }

    /**
     * Bottom sheet action listener
     *
     * @param bottomSheet
     * @param obj
     */
    @Override
    public void onSheetActionClick(BottomSheet bottomSheet, Object obj) {
        mSheet.dismiss();
        Cursor cr = (Cursor) obj;
        Bundle bundle = new Bundle();
        bundle.putInt(KEY_NOTE_ID, cr.getInt(cr.getColumnIndex(OColumn.ROW_ID)));
        IntentUtils.startActivity(getActivity(), NoteDetail.class, bundle);
    }

    @Override
    public void onClick(View v) {
        Bundle data = new Bundle();
        data.putInt(KEY_STAGE_ID, mStageId);
        switch (v.getId()) {
        case R.id.fabButton:
            showFabSheet();
            break;
        }
    }

    private void showFabSheet() {
        if (mSheet != null) {
            mSheet.dismiss();
        }
        BottomSheet.Builder builder = new BottomSheet.Builder(getActivity());
        builder.listener(fabListeners);
        builder.setIconColor(_c(R.color.body_text_2));
        builder.setTextColor(_c(R.color.body_text_1));
        builder.title("New Note");
        builder.menu(R.menu.menu_notes_sheet);
        mSheet = builder.create();
        mSheet.show();
    }

    BottomSheetListeners.OnSheetItemClickListener fabListeners = new BottomSheetListeners.OnSheetItemClickListener() {

        @Override
        public void onItemClick(BottomSheet bottomSheet, MenuItem menuItem, Object o) {
            if (mSheet != null) {
                mSheet.dismiss();
            }
            Bundle data = new Bundle();
            data.putInt(KEY_STAGE_ID, mStageId);
            if (extra.containsKey("tag_id")) {
                data.putInt("tag_id", extra.getInt("tag_id"));
            }
            switch (menuItem.getItemId()) {
            case R.id.menu_note_create:
                quickCreateNote(data);
                break;
            case R.id.menu_note_new_with_attachment:
                CheckForDocumentModule checkForDocumentModule = new CheckForDocumentModule();
                checkForDocumentModule.execute();
                break;
            case R.id.menu_note_speech_to_text:
                data.putString("type", "speechToText");
                quickCreateNote(data);
                break;
            }
        }
    };

    private class CheckForDocumentModule extends AsyncTask<Void, Void, Boolean> {

        ProgressDialog progressDialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressDialog = new ProgressDialog(getActivity());
            progressDialog.setTitle(R.string.title_please_wait);
            progressDialog.setMessage(_s(R.string.title_working));
            progressDialog.setCancelable(false);
            progressDialog.show();
        }

        @Override
        protected Boolean doInBackground(Void... params) {
            return db().isInstalledOnServer("document", false);
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            progressDialog.dismiss();
            if (result) {
                Bundle data = new Bundle();
                data.putInt(KEY_STAGE_ID, mStageId);
                if (extra.containsKey("tag_id")) {
                    data.putInt("tag_id", extra.getInt("tag_id"));
                }
                data.putBoolean(NoteDetail.REQUEST_FILE_ATTACHMENT, true);
                quickCreateNote(data);
            } else {
                OAlert.showWarning(getActivity(), _s(R.string.warning_no_document_module_installed));
            }
        }
    }

    private void quickCreateNote(Bundle data) {
        IntentUtils.startActivity(getActivity(), NoteDetail.class, data);
    }

    @Override
    public List<ODrawerItem> drawerMenus(Context context) {
        return null;
    }

    @Override
    public Class<NoteNote> database() {
        return NoteNote.class;
    }

    @Override
    public void onStatusChange(Boolean refreshing) {
        if (getActivity() != null)
            getLoaderManager().restartLoader(0, null, this);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle data) {
        String selection = "";
        List<String> args = new ArrayList<>();
        Uri uri = db().uri();
        switch (mCurrentKey) {
        case Notes:
            args.add(mStageId + "");
            selection += "stage_id = ? and open = ? and trashed = ?";
            args.add("true");
            args.add("0");
            break;
        case Reminders:
            selection += " reminder != ?";
            args.add("0");
            break;
        case Archive:
            selection += " open = ? and trashed = ?";
            args.add("false");
            args.add("0");
            break;
        case Deleted:
            selection += " trashed = ?";
            args.add("1");
            break;
        case TagFilter:
            uri = ((NoteNote) db()).filterTag();
            args.add(extra.getInt("tag_id") + "");
            break;
        }
        if (mFilter != null) {
            selection += " and name like ?";
            args.add("%" + mFilter + "%");
        }
        String[] arguments = args.toArray(new String[args.size()]);
        return new CursorLoader(getActivity(), uri, null, selection, arguments, " sequence");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, final Cursor data) {
        mAdapter.changeCursor(data);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (data.getCount() > 0) {
                    OControls.setGone(mView, R.id.loadingProgress);
                    OControls.setVisible(mView, R.id.swipe_container);
                    OControls.setGone(mView, R.id.notes_no_items);
                    setHasSwipeRefreshView(mView, R.id.swipe_container, Notes.this);
                } else {
                    OControls.setGone(mView, R.id.loadingProgress);
                    OControls.setGone(mView, R.id.swipe_container);
                    OControls.setVisible(mView, R.id.notes_no_items);
                    setHasSwipeRefreshView(mView, R.id.notes_no_items, Notes.this);
                    switch (mCurrentKey) {
                    case Notes:
                        OControls.setText(mView, R.id.title, R.string.label_no_notes_found);
                        OControls.setImage(mView, R.id.icon, R.drawable.ic_action_notes);
                        break;
                    case Archive:
                        OControls.setText(mView, R.id.title, getString(R.string.label_archived_note_here));
                        OControls.setImage(mView, R.id.icon, R.drawable.ic_action_archive);
                        break;
                    case Reminders:
                        OControls.setText(mView, R.id.title, getString(R.string.label_upcoming_reminder_note));
                        OControls.setImage(mView, R.id.icon, R.drawable.ic_action_reminder);
                        break;
                    case Deleted:
                        OControls.setText(mView, R.id.title, R.string.label_empty_trash);
                        OControls.setImage(mView, R.id.icon, R.drawable.ic_action_trash);
                        break;
                    case TagFilter:
                        OControls.setText(mView, R.id.title, R.string.label_empty_tag_list);
                        OControls.setImage(mView, R.id.icon, R.drawable.ic_action_label);
                        break;
                    }
                }
            }
        }, 500);

    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.changeCursor(null);
    }

    @Override
    public void onRefresh() {
        if (inNetwork()) {
            parent().sync().requestSync(NoteNote.AUTHORITY);
            setSwipeRefreshing(true);
        } else {
            hideRefreshingProgress();
            Toast.makeText(getActivity(), _s(R.string.toast_network_required), Toast.LENGTH_LONG).show();
        }
    }

    @Override
    public void onViewBind(View view, Cursor cursor, ODataRow row) {
        int color_number = row.getInt("color");
        view.findViewById(R.id.note_bg_color).setBackgroundColor(NoteUtil.getBackgroundColor(color_number));
        OControls.setText(view, R.id.note_memo, StringUtils.htmlToString(row.getString("short_memo")));
        OControls.setTextColor(view, R.id.note_memo, NoteUtil.getTextColor(color_number));
        OControls.setTextColor(view, R.id.note_reminder_status, NoteUtil.getTextColor(color_number));
        ImageView attachment = (ImageView) view.findViewById(R.id.noteHasAttachment);
        attachment.setColorFilter(NoteUtil.getTextColor(color_number));
        boolean showContainer = true;
        if (((NoteNote) db()).hasAttachment(row.getInt(OColumn.ROW_ID))) {
            attachment.setVisibility(View.VISIBLE);
        } else {
            showContainer = false;
            attachment.setVisibility(View.GONE);
        }
        ImageView reminderClock = (ImageView) view.findViewById(R.id.reminderClock);
        reminderClock.setColorFilter(NoteUtil.getTextColor(color_number));
        if (!row.getString("reminder").equals("0")) {
            view.findViewById(R.id.reminderClock).setVisibility(View.VISIBLE);
            OControls.setText(view, R.id.note_reminder_status, row.getString("reminder"));
        } else {
            if (!showContainer)
                showContainer = false;
            view.findViewById(R.id.reminderClock).setVisibility(View.GONE);
            OControls.setText(view, R.id.note_reminder_status, "");
        }
        view.findViewById(R.id.note_info_container).setVisibility((!showContainer) ? View.GONE : View.VISIBLE);
        bindRowControls(view, row);
    }

    private void bindRowControls(final View view, final ODataRow row) {
        ImageView imgMove = (ImageView) view.findViewById(R.id.note_move);
        if (mCurrentKey != Type.Notes)
            imgMove.setVisibility(View.GONE);
        imgMove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                moveTo(row.getInt(OColumn.ROW_ID), row);
            }
        });
    }

    private void chooseColor(final int row_id, ODataRow row) {
        int color = row.getInt("color");
        String selected_color = NoteUtil.getBackgroundColors()[color];
        NoteUtil.colorDialog(getActivity(), selected_color, new NoteColorDialog.OnColorSelectListener() {
            @Override
            public void colorSelected(ODataRow color_data) {
                int index = color_data.getInt("index");
                OValues values = new OValues();
                values.put("color", index);
                values.put("trashed", 0);
                values.put("is_dirty", true);
                db().update(row_id, values);
                restartLoader();
            }
        }).show();
    }

    private void showArchiveUndoBar(final int row_id, final String open, final boolean fromTrash) {
        OValues values = new OValues();
        values.put("open", open);
        values.put("trashed", 0);
        db().update(row_id, values);
        restartLoader();
        String toast = (open.equals("true")) ? _s(R.string.snack_note_unarchived)
                : _s(R.string.snack_note_archived);
        if (fromTrash) {
            toast = _s(R.string.snack_note_restored);
        }
        SnackBar.get(getActivity()).text(toast).duration(SnackbarBuilder.SnackbarDuration.LENGTH_LONG)
                .actionColor(_c(R.color.theme_secondary_light))
                .withAction(R.string.undo, new ActionClickListener() {
                    @Override
                    public void onActionClicked(SnackbarBuilder snackbarBuilder) {
                        OValues value = new OValues();
                        if (!fromTrash) {
                            value.put("open", (open.equals("true")) ? "false" : "true");
                        }
                        value.put("trashed", (fromTrash) ? 1 : 0);
                        db().update(row_id, value);
                    }
                }).withEventListener(this).show();
    }

    private void showTrashUndoBar(final int row_id, final int trashed) {
        final OValues values = new OValues();
        values.put("trashed", trashed);
        values.put("_is_dirty", false);
        values.put("trashed_date", ODateUtils.getUTCDate());
        if (mCurrentKey == Type.Deleted) {
            values.put("open", "false");
        }
        db().update(row_id, values);
        restartLoader();
        SnackBar.get(getActivity()).text(R.string.snack_note_moved_to_recycle_bin)
                .duration(SnackbarBuilder.SnackbarDuration.LENGTH_LONG)
                .actionColor(_c(R.color.theme_secondary_light))
                .withAction(R.string.undo, new ActionClickListener() {
                    @Override
                    public void onActionClicked(SnackbarBuilder snackbarBuilder) {
                        OValues value = new OValues();
                        value.put("trashed", 0);
                        value.put("_is_dirty", false);
                        db().update(row_id, value);
                    }
                })

                .withEventListener(this).show();
    }

    private void moveTo(final int row_id, ODataRow row) {
        NoteUtil.noteStages(getActivity(), row.getInt("stage_id"), new NoteStagesDialog.OnStageSelectListener() {
            @Override
            public void stageSelected(ODataRow row) {
                int stage_id = row.getInt(OColumn.ROW_ID);
                OValues values = new OValues();
                values.put("stage_id", stage_id);
                values.put("is_dirty", true);
                db().update(row_id, values);
                restartLoader();
                String toast = String.format(_s(R.string.snack_note_moved_to), row.getString("name"));
                Toast.makeText(getActivity(), toast, Toast.LENGTH_LONG).show();
            }
        }).show();
    }

    private void restartLoader() {
        getLoaderManager().restartLoader(0, null, this);
    }

    @Override
    protected void onNavSpinnerDestroy() {
        if (mStageId == 0) {
            super.onNavSpinnerDestroy();
        }
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        menu.clear();
        inflater.inflate(R.menu.menu_notes, menu);
        setHasSearchView(this, menu, R.id.menu_note_search);
    }

    @Override
    public boolean onSearchViewTextChange(String newFilter) {
        mFilter = newFilter;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

    @Override
    public void onSearchViewClose() {
        // nothing to do
    }

    @Override
    public boolean onBackPressed() {
        if (mSheet != null && mSheet.isShowing()) {
            mSheet.dismiss();
            return false;
        }
        return true;
    }

    // Snack bar listeners
    @Override
    public void onShow(int i) {
        hideFab();
    }

    @Override
    public void onDismiss(int i) {
        showFab();
    }
}