/***********************************************************************************

    Copyright (C) 2007-2018 Ahmet Öztürk (aoz_2@yahoo.com)

    This file is part of Lifeograph.

    Lifeograph is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Lifeograph 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Lifeograph.  If not, see <http://www.gnu.org/licenses/>.

***********************************************************************************/


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "lifeograph.hpp"
#include "app_window.hpp"
#include "view_entry.hpp"
#include "printing.hpp"


using namespace LIFEO;


EntryView::EntryView()
{
    Entry::shower = this;

    Gtk::Button* button_print;

    Gtk::Button* button_hide( nullptr );
    Gtk::Button* button_hide_before( nullptr );
    Gtk::Button* button_hide_after( nullptr );

    try
    {
        auto builder{ Lifeograph::get_builder() };
        builder->get_widget( "Bx_entry", m_box );
        builder->get_widget( "Po_entry", m_Po_elem );
        builder->get_widget( "RB_entry_not_todo", m_RB_not_todo );
        builder->get_widget( "RB_entry_todo", m_RB_todo );
        builder->get_widget( "RB_entry_progressed", m_RB_progressed );
        builder->get_widget( "RB_entry_done", m_RB_done );
        builder->get_widget( "RB_entry_canceled", m_RB_canceled );
        builder->get_widget( "L_entry_created", m_L_created );
        builder->get_widget( "L_entry_edited", m_L_edited );
        builder->get_widget( "L_entry_status", m_L_status );
        builder->get_widget( "L_entry_status_changed", m_L_status_changed );
        builder->get_widget( "TB_entry_favorite", m_TB_toggle_favorite );
        builder->get_widget( "B_entry_print", button_print );
        builder->get_widget( "B_entry_filter", button_hide );
        builder->get_widget( "B_entry_filter_before", button_hide_before );
        builder->get_widget( "B_entry_filter_after", button_hide_after );
        builder->get_widget( "B_entry_trash", m_B_trash );
        builder->get_widget( "B_entry_restore", m_B_restore );
        builder->get_widget( "B_entry_dismiss", m_B_dismiss );

        builder->get_widget( "Bx_entry_toolbar_text", m_Bx_editing_toolbar );
        builder->get_widget( "B_entry_bold", m_B_bold );
        builder->get_widget( "B_entry_italic", m_B_italic );
        builder->get_widget( "B_entry_strikethrough", m_B_strikethrough );
        builder->get_widget( "B_entry_highlight", m_B_highlight );
        builder->get_widget( "L_entry_highlight", m_L_highlight );
        builder->get_widget( "EB_entry_highlight", m_EB_highlight );
        builder->get_widget( "MB_entry_list_item", m_MB_list_item );
        builder->get_widget( "MI_entry_list_item_none", m_MI_list_none );
        builder->get_widget( "MI_entry_list_item_bullet", m_MI_list_bullet );
        builder->get_widget( "MI_entry_list_item_todo", m_MI_list_todo );
        builder->get_widget( "MI_entry_list_item_progressed", m_MI_list_progressed );
        builder->get_widget( "MI_entry_list_item_done", m_MI_list_done );
        builder->get_widget( "MI_entry_list_item_canceled", m_MI_list_canceled );
        builder->get_widget( "TB_entry_comments", m_TB_comments );
        builder->get_widget_derived( "TV_entry", m_textview );

        builder->get_widget_derived( "DA_entry_tags", m_W_tag_list );

        // THEMABLE ICONS
        Gtk::Image* img;
        builder->get_widget( "I_entry_not_todo", img );
        img->set( Lifeograph::icons->todo_auto_32 );
        builder->get_widget( "I_entry_todo", img );
        img->set( Lifeograph::icons->todo_open_32 );
        builder->get_widget( "I_entry_progressed", img );
        img->set( Lifeograph::icons->todo_progressed_32 );
        builder->get_widget( "I_entry_done", img );
        img->set( Lifeograph::icons->todo_done_32 );
        builder->get_widget( "I_entry_canceled", img );
        img->set( Lifeograph::icons->todo_canceled_32 );

        builder->get_widget( "I_entry_list_item_bullet", img );
        img->set( Lifeograph::icons->bullet_16 );
        builder->get_widget( "I_entry_list_item_todo", img );
        img->set( Lifeograph::icons->todo_open_16 );
        builder->get_widget( "I_entry_list_item_progressed", img );
        img->set( Lifeograph::icons->todo_progressed_16 );
        builder->get_widget( "I_entry_list_item_done", img );
        img->set( Lifeograph::icons->todo_done_16 );
        builder->get_widget( "I_entry_list_item_canceled", img );
        img->set( Lifeograph::icons->todo_canceled_16 );

        builder->get_widget( "I_entry_favorite", img );
        img->set( Lifeograph::icons->favorite_16 );

        builder->get_widget( "I_header_overlay", img );
        img->set( Lifeograph::icons->favorite_16 );
    }
    catch( ... )
    {
        throw LIFEO::Error( "Failed to create the entry view" );
    }

    // TEXT VIEW
    m_textview->drag_dest_get_target_list()->add( Lifeograph::p->drag_targets_tag );
    m_textview->drag_dest_get_target_list()->add( Lifeograph::p->drag_targets_entry );

    // TAGS WIDGET
    m_W_tag_list->drag_dest_set( Lifeograph::p->drag_targets_tag );

    // SIGNALS
    m_textview->m_buffer->signal_changed().connect(
            sigc::mem_fun( this, &LIFEO::EntryView::handle_textview_changed ) );

    m_RB_not_todo->signal_toggled().connect(
            sigc::bind( sigc::mem_fun( this, &EntryView::set_todo_status ), ES::NOT_TODO ) );
    m_RB_todo->signal_toggled().connect(
            sigc::bind( sigc::mem_fun( this, &EntryView::set_todo_status ), ES::TODO ) );
    m_RB_progressed->signal_toggled().connect(
            sigc::bind( sigc::mem_fun( this, &EntryView::set_todo_status ), ES::PROGRESSED ) );
    m_RB_done->signal_toggled().connect(
            sigc::bind( sigc::mem_fun( this, &EntryView::set_todo_status ), ES::DONE ) );
    m_RB_canceled->signal_toggled().connect(
            sigc::bind( sigc::mem_fun( this, &EntryView::set_todo_status ), ES::CANCELED ) );

    m_TB_toggle_favorite->signal_toggled().connect(
            sigc::mem_fun( this, &LIFEO::EntryView::toggle_favoredness ) );
    m_B_trash->signal_clicked().connect(
            sigc::mem_fun( this, &LIFEO::EntryView::trash_entry ) );
    m_B_restore->signal_clicked().connect(
            sigc::mem_fun( this, &LIFEO::EntryView::restore_entry ) );
    m_B_dismiss->signal_clicked().connect(
            sigc::mem_fun( this, &LIFEO::EntryView::dismiss_entry ) );
    button_print->signal_clicked().connect(
            sigc::mem_fun( this, &EntryView::print ) );
    button_hide->signal_clicked().connect( sigc::mem_fun( this, &EntryView::hide ) );
    button_hide_before->signal_clicked().connect(
            sigc::mem_fun( this, &EntryView::hide_before ) );
    button_hide_after->signal_clicked().connect(
            sigc::mem_fun( this, &EntryView::hide_after ) );

    m_MI_list_bullet->signal_activate().connect( sigc::bind(
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::set_list_item_mark ), '*' ) );
    m_MI_list_none->signal_activate().connect( sigc::bind(
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::set_list_item_mark ), 0 ) );
    m_MI_list_todo->signal_activate().connect( sigc::bind(
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::set_list_item_mark ), ' ' ) );
    m_MI_list_progressed->signal_activate().connect( sigc::bind(
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::set_list_item_mark ), '~' ) );
    m_MI_list_done->signal_activate().connect( sigc::bind(
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::set_list_item_mark ), '+' ) );
    m_MI_list_canceled->signal_activate().connect( sigc::bind(
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::set_list_item_mark ), 'x' ) );

    m_textview->signal_drag_data_received().connect(
            sigc::mem_fun( this, &EntryView::handle_drag_data_received ) );
    m_textview->signal_focus_in_event().connect_notify(
            sigc::hide( sigc::mem_fun( m_W_tag_list, &WidgetEntryTags::hide_popover ) ) );

    m_W_tag_list->signal_drag_data_received().connect(
            sigc::mem_fun( this, &EntryView::handle_drag_data_received ) );
    m_W_tag_list->signal_tag_double_clicked().connect(
            sigc::mem_fun( this, &EntryView::show_tag ) );
    m_W_tag_list->signal_theme_changed().connect(
            sigc::mem_fun( this, &EntryView::update_theme ) );

    // EDITOR ACTIONS
    Lifeograph::create_action(
            true, m_action_bold, "Bold", "", "",
            Gtk::AccelKey( GDK_KEY_b, Gdk::CONTROL_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::toggle_bold ),
            m_B_bold );
    Lifeograph::create_action(
            true, m_action_italic, "Italic", "", "",
            Gtk::AccelKey( GDK_KEY_i, Gdk::CONTROL_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::toggle_italic ),
            m_B_italic );
    Lifeograph::create_action(
            true, m_action_strikethrough, "Strikethrough", "", "",
            Gtk::AccelKey( GDK_KEY_s, Gdk::CONTROL_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::toggle_strikethrough ),
            m_B_strikethrough );
    Lifeograph::create_action(
            true, m_action_highlight, "Highlight", "", "",
            Gtk::AccelKey( GDK_KEY_h, Gdk::CONTROL_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::toggle_highlight ),
            m_B_highlight );

    Lifeograph::create_action(
            true, m_action_focus_tag, "FocusTag", "", "",
            Gtk::AccelKey( GDK_KEY_t, Gdk::CONTROL_MASK ),
            sigc::mem_fun( m_W_tag_list, &WidgetEntryTags::start_editing ) );

    Lifeograph::create_toggle_action(
            false, m_action_toggle_comments, "ToggleComments", "", "",
            Gtk::AccelKey( GDK_KEY_c, Gdk::MOD1_MASK ),
            sigc::mem_fun( this, &EntryView::toggle_comments ),
            m_TB_comments );

    Lifeograph::create_action(
            true, m_action_indent, "Indent", "", "",
            Gtk::AccelKey( GDK_KEY_i, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::handle_indent ) );
    Lifeograph::create_action(
            true, m_action_unindent, "Unindent", "", "",
            Gtk::AccelKey( GDK_KEY_u, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::handle_unindent ) );

    Lifeograph::create_action(
            true, m_action_add_empty_line_above, "AddEmptyLineAbove", "", "",
            Gtk::AccelKey( GDK_KEY_l, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::add_empty_line_above ) );
    Lifeograph::create_action(
            true, m_action_remove_empty_line_above, "RemoveEmptyLineAbove", "", "",
            Gtk::AccelKey( GDK_KEY_l, Gdk::MOD1_MASK|Gdk::SHIFT_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::remove_empty_line_above ) );

    Lifeograph::create_action(
            true, m_action_move_line_up, "MoveLineUp", "", "",
            Gtk::AccelKey( GDK_KEY_Up, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::move_line_up ) );
    Lifeograph::create_action(
            true, m_action_move_line_down, "MoveLineDown", "", "",
            Gtk::AccelKey( GDK_KEY_Down, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::move_line_down ) );
    Lifeograph::create_action(
            true, m_action_delete_paragraph, "DeleteParagraph", "", "",
            Gtk::AccelKey( GDK_KEY_x, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::delete_paragraphs ) );

    Lifeograph::create_action(
            true, m_action_time_stamp, "TimeStamp", "", "",
            Gtk::AccelKey( GDK_KEY_t, Gdk::MOD1_MASK ),
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::insert_time_stamp ) );

    Lifeograph::p->add_action( "duplicate_paragraph",
            sigc::mem_fun( m_textview->m_buffer, &TextbufferDiary::duplicate_paragraphs ) );
    Lifeograph::p->set_accel_for_action( "app.duplicate_paragraph", "<Alt>2" );
}

void
EntryView::sync()
{
    if( m_flag_entrychanged )
    {
        m_entry_sync->set_date_edited( time( nullptr ) );
        //shouln't be needed any longer: m_entry_sync->set_text( m_textview->m_buffer->get_text() );
        m_flag_entrychanged = false;
        PRINT_DEBUG( "entry synced" );
    }
}

/*void
EntryView::remove_selected_tags()
{
    std::vector< Gtk::TreeModel::Path > selected_items =
            m_iconview_tags->get_selected_items();
    for( std::vector< Gtk::TreeModel::Path >::iterator iter = selected_items.begin();
         iter != selected_items.end();
         ++iter )
    {
        Gtk::TreeRow row = *m_liststore_tags->get_iter( *iter );
        DiaryElement* element = row[ PanelExtra::colrec->ptr ];
        Tag* tag = dynamic_cast< Tag* >( element );

        m_ptr2elem->remove_tag( tag );
        m_liststore_tags->erase( row );
    }
}*/

void
EntryView::handle_login()
{
    m_textview->m_buffer->handle_login();

    // READ ONLY
    bool editable( ! Diary::d->is_read_only() );
    m_textview->set_editable( editable );
    m_W_tag_list->set_editable( editable );
    m_RB_not_todo->set_visible( editable );
    m_RB_todo->set_visible( editable );
    m_RB_progressed->set_visible( editable );
    m_RB_done->set_visible( editable );
    m_RB_canceled->set_visible( editable );
    //m_menuseparator_4->set_visible( editable );
    m_TB_toggle_favorite->set_visible( editable );
    //m_menuseparator_1->set_visible( editable );
    //m_menuseparator_2->set_visible( editable );
    m_B_trash->set_visible( editable );
    m_B_restore->set_visible( editable );
    m_B_dismiss->set_visible( editable );
    m_Bx_editing_toolbar->set_visible( Lifeograph::settings.show_formatting_toolbar &&
                                       editable );
}

void
EntryView::handle_logout()
{
    m_textview->m_buffer->handle_logout();
    m_W_tag_list->set_entry( nullptr );
}

void
EntryView::handle_textview_changed()
{
    if( Lifeograph::s_internaloperation ) return;

    m_flag_entrychanged = true;

    PRINT_DEBUG( "entry changed" );

    // TODO:
    //if( m_hbox_tagtools->is_visible() )
        //m_hbox_tagtools->hide();
}

void
EntryView::handle_drag_data_received(
                const Glib::RefPtr< Gdk::DragContext >& context,
                int x, int y,
                const Gtk::SelectionData& selection_data,
                guint info,
                guint time )
{
    if( Diary::d->is_read_only() )
        return;

    context->drag_finish( true, false, time );

    if( Lifeograph::s_elem_dragged == nullptr )
        return;

    switch( Lifeograph::s_elem_dragged->get_type() )
    {
        case DiaryElement::ET_ENTRY:
            m_textview->m_buffer->insert_link( Lifeograph::s_elem_dragged );
            break;
        case DiaryElement::ET_TAG:
        {
            Tag* tag = dynamic_cast< Tag* >( Lifeograph::s_elem_dragged );
            if( m_ptr2elem->add_tag( tag ) ) // if does not already have the tag
            {
                m_W_tag_list->redraw();
                if( tag->get_has_own_theme() )
                    update_theme();
                // note: even if tag has its own theme it is not applied if entry has already
                // a theme tag before
            }
            break;
        }
        case DiaryElement::ET_UNTAGGED:
            if( m_ptr2elem->clear_tags() )
            {
                m_W_tag_list->redraw();
                update_theme();
            }
            break;
        default:
            break;
    }
}

void
toggle_entry_favoredness( Entry* e )
{
    e->toggle_favored();
    AppWindow::p->panel_diary->handle_elem_changed( e );
}
void
EntryView::toggle_favoredness()
{
    if( Lifeograph::s_internaloperation )
        return;

    if( AppWindow::p->panel_diary->get_selected_count() > 1 )
    {
        sigc::slot< void, Entry* > s = sigc::ptr_fun( toggle_entry_favoredness );
        AppWindow::p->panel_diary->do_for_each_selected_entry( s );
    }
    else
    {
        m_ptr2elem->toggle_favored();
        AppWindow::p->panel_diary->handle_elem_changed( m_ptr2elem );
    }

    AppWindow::p->panel_main->update_overlay_icon();
}

void
set_entry_todo_status( Entry* e, ElemStatus status )
{
    if( status == ES::NOT_TODO )
        e->calculate_todo_status();
    else
    {
        e->set_todo_status( status );
        e->set_date_status( time( nullptr ) );
    }
    AppWindow::p->panel_diary->handle_elem_changed( e );
}
void
EntryView::set_todo_status( ElemStatus status )
{
    if( Lifeograph::s_internaloperation )
        return;

    if( AppWindow::p->panel_diary->get_selected_count() > 1 )
    {
        sigc::slot< void, Entry* > s =
                sigc::bind( sigc::ptr_fun( set_entry_todo_status ), status );
        AppWindow::p->panel_diary->do_for_each_selected_entry( s );
    }
    else
        set_entry_todo_status( m_ptr2elem, status );

    AppWindow::p->panel_main->set_icon( m_ptr2elem->get_icon32() );
    update_status_date();
}

void
EntryView::print()
{
    AppWindow::p->panel_main->hide_popover();

    AppWindow::p->m_entry_view->sync();

    Glib::RefPtr< PrintOpr > print = PrintOpr::create();

    try
    {
        AppWindow::p->freeze_auto_logout();
        print->set_hide_comments( m_TB_comments->get_active() );
        print->run( Gtk::PRINT_OPERATION_ACTION_PRINT_DIALOG, *AppWindow::p );
        AppWindow::p->unfreeze_auto_logout();
    }
    catch( const Gtk::PrintError &ex )
    {
        // See documentation for exact Gtk::PrintError error codes:
        print_error( "An error occurred while trying to run a print operation:",
                ex.what() );
    }
}

void
EntryView::hide()
{
    AppWindow::p->panel_main->hide_popover();

    Diary::d->get_filter()->add_entry( m_ptr2elem );
    AppWindow::p->panel_diary->update_calendar();
    AppWindow::p->panel_diary->update_entry_list();
}

void
EntryView::hide_before()
{
    Diary::d->set_filter_date_begin( m_ptr2elem->get_date_t() );
    AppWindow::p->panel_diary->update_calendar();
    AppWindow::p->panel_diary->update_entry_list();
}

void
EntryView::hide_after()
{
    Diary::d->set_filter_date_end( m_ptr2elem->get_date_t() );
    AppWindow::p->panel_diary->update_calendar();
    AppWindow::p->panel_diary->update_entry_list();
}

void
EntryView::update_theme()
{
    m_textview->m_buffer->set_theme( m_ptr2elem->get_theme() );
    update_highlight_button();
}

void
EntryView::trash_entry()
{
    AppWindow::p->panel_main->hide_popover();

    m_ptr2elem->set_trashed( true );

    if( !( Diary::d->get_filter()->get_status() & ES::SHOW_TRASHED ) )
    {
        Diary::d->show();
        AppWindow::p->panel_main->remove_element_from_history( m_ptr2elem );
        if( Diary::d->get_startup_elem() == m_ptr2elem )
        {
            Diary::d->set_startup_elem( DEID_DIARY );
            AppWindow::p->m_diary_view->update_startup_elem();
        }
        Diary::d->get_filter()->set_status_outstanding();
    }
    else
    {
        m_B_trash->set_visible( false );
        m_B_restore->set_visible( true );
        m_B_dismiss->set_visible( true );
    }

    Lifeograph::s_internaloperation++;

    AppWindow::p->panel_diary->update_calendar();
    AppWindow::p->panel_diary->update_entry_list();

    Lifeograph::s_internaloperation--;
}

void
EntryView::restore_entry()
{
    AppWindow::p->panel_main->hide_popover();

    m_ptr2elem->set_trashed( false );

    m_B_trash->set_visible( true );
    m_B_restore->set_visible( false );
    m_B_dismiss->set_visible( false );

    Diary::d->get_filter()->set_status_outstanding();

    Lifeograph::s_internaloperation++;

    AppWindow::p->panel_diary->update_calendar();
    AppWindow::p->panel_diary->update_entry_list();

    Lifeograph::s_internaloperation--;
}

void
EntryView::dismiss_entry()
{
    AppWindow::p->panel_main->hide_popover();

    if( ! AppWindow::p->confirm_dismiss_element( m_ptr2elem ) )
        return;

    // first we need to make sure that the tag list widget will not try to update
    // or a segfault will ensue:
    m_W_tag_list->set_entry( nullptr );

    Lifeograph::s_internaloperation++;

    AppWindow::p->panel_main->remove_element_from_history( m_ptr2elem );
    Diary::d->dismiss_entry( m_ptr2elem );

    AppWindow::p->panel_diary->update_calendar();
    AppWindow::p->panel_diary->update_entry_list();

    Lifeograph::s_internaloperation--;
}

void
EntryView::toggle_comments()
{
    if( AppWindow::p->panel_main->get_cur_elem_type() == DiaryElement::ET_ENTRY )
        m_textview->m_buffer->set_comment_visibility(
                ! m_textview->m_buffer->get_comment_visibility() );
}

bool
EntryView::check_title_applicable( const Glib::ustring& str ) const
{
    return( Date::parse_string( nullptr, str ) == OK );
    // TODO communicate the nature of the error to the user (possibly via a tooltip)
}

bool
EntryView::apply_title( const Glib::ustring& str )
{
    Date date( str );
    if( !date.is_set() )
        return false;

    if( !date.is_ordinal() )
        date.reset_order_1();

    Diary::d->set_entry_date( m_ptr2elem, date );
    AppWindow::p->panel_diary->update_entry_list();
    AppWindow::p->panel_diary->select_date_in_calendar( m_ptr2elem->get_date() );

    return true;
}

void
EntryView::show_tag( const Tag* tag )
{
    const_cast< Tag* >( tag )->show();
}

void
EntryView::show( Entry& entry )
{
    // do nothing if entry is already the current element:
    if( AppWindow::p->panel_main->is_cur_elem( &entry ) )
        return;

    m_ptr2elem = &entry; // must be first thing

    m_W_tag_list->hide_popover();

    AppWindow::p->panel_main->show( this );
    m_L_created->set_text( m_ptr2elem->get_date_created_str() );
    m_L_edited->set_text( m_ptr2elem->get_date_edited_str() );
    update_status_date();

    Lifeograph::s_internaloperation++;

    if( ! Diary::d->is_read_only() )
    {
        m_TB_toggle_favorite->set_active( entry.is_favored() );
        m_B_trash->set_visible( !entry.is_trashed() );
        m_B_restore->set_visible( entry.is_trashed() );
        m_B_dismiss->set_visible( entry.is_trashed() );

        switch( m_ptr2elem->get_todo_status() )
        {
            case ES::TODO:
                m_RB_todo->set_active();
                break;
            case ES::PROGRESSED:
                m_RB_progressed->set_active();
                break;
            case ES::DONE:
                m_RB_done->set_active();
                break;
            case ES::CANCELED:
                m_RB_canceled->set_active();
                break;
            case ES::NOT_TODO:
            default:
                m_RB_not_todo->set_active();
                break;
        }
    }

    // TOOLBAR
    update_highlight_button();

    // BODY
    m_textview->set_richtext( &entry );
    // unfortunately, word count is only ready after parse which occurs in set_richtext:
    AppWindow::p->panel_main->refresh_extra_info();

    Lifeograph::s_internaloperation--;

    m_W_tag_list->set_entry( &entry );

    m_entry_sync = m_ptr2elem;

    PRINT_DEBUG( "entry shown" );
}

void
EntryView::prepare_for_hiding( Entry& entry )
{
    sync();
    m_W_tag_list->clear();
    PRINT_DEBUG( "EntryView::prepare_for_hiding()" );
}

void
EntryView::update_formatting_toolbar()
{
    m_Bx_editing_toolbar->set_visible( Lifeograph::settings.show_formatting_toolbar &&
                                       Diary::d->is_read_only() == false );
}

void
EntryView::update_highlight_button()
{
    const Theme* theme = m_ptr2elem->get_theme();
    m_L_highlight->override_color( theme->color_text, Gtk::STATE_FLAG_NORMAL );
    m_L_highlight->override_color( theme->color_text, Gtk::STATE_FLAG_PRELIGHT );
    m_L_highlight->override_color( theme->color_text, Gtk::STATE_FLAG_ACTIVE );
    m_EB_highlight->override_background_color(
            theme->color_highlight, Gtk::STATE_FLAG_NORMAL );
    m_EB_highlight->override_background_color(
            theme->color_highlight, Gtk::STATE_FLAG_PRELIGHT );
    m_EB_highlight->override_background_color(
            theme->color_highlight, Gtk::STATE_FLAG_ACTIVE );
}

void
EntryView::update_status_date()
{
    ElemStatus es = m_ptr2elem->get_todo_status_effective();

    m_L_status->set_visible( es != ES::NOT_TODO );
    m_L_status_changed->set_visible( es != ES::NOT_TODO );

    if( es != ES::NOT_TODO )
        m_L_status_changed->set_text( m_ptr2elem->get_date_status_str() );

    switch( es )
    {
        case ES::TODO:
            m_L_status->set_text( _( "Opened" ) );
            break;
        case ES::PROGRESSED:
            m_L_status->set_text( _( "Started" ) );
            break;
        case ES::DONE:
            m_L_status->set_text( _( "Completed" ) );
            break;
        case ES::CANCELED:
            m_L_status->set_text( _( "Canceled" ) );
            break;
    }
}
