lib: removed dead code from Bookmark parser
[barry/progweb.git] / desktop / src / Mode_Browse.cc
blob49b268c5bf8e43368e37356cb3072e5d04239ff0
1 ///
2 /// \file Mode_Browse.cc
3 /// Mode derived class for database browsing
4 ///
6 /*
7 Copyright (C) 2011-2012, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "Mode_Browse.h"
23 #include "BaseFrame.h"
24 #include "ContactEditDlg.h"
25 #include "windowids.h"
26 #include <iostream>
27 #include <sstream>
28 #include <iomanip>
30 using namespace std;
31 using namespace Barry;
33 BEGIN_EVENT_TABLE(BrowseMode, wxEvtHandler)
34 EVT_LIST_ITEM_SELECTED(BrowseMode_DBDBList,
35 BrowseMode::OnDBDBListSelChange)
36 EVT_LIST_ITEM_SELECTED(BrowseMode_RecordList,
37 BrowseMode::OnRecordListSelChange)
38 EVT_LIST_ITEM_ACTIVATED(BrowseMode_RecordList,
39 BrowseMode::OnRecordListActivated)
40 EVT_CHECKBOX (BrowseMode_ShowAllCheckbox,
41 BrowseMode::OnShowAll)
42 EVT_BUTTON (BrowseMode_AddRecordButton,
43 BrowseMode::OnAddRecord)
44 EVT_BUTTON (BrowseMode_CopyRecordButton,
45 BrowseMode::OnCopyRecord)
46 EVT_BUTTON (BrowseMode_EditRecordButton,
47 BrowseMode::OnEditRecord)
48 EVT_BUTTON (BrowseMode_DeleteRecordButton,
49 BrowseMode::OnDeleteRecord)
50 END_EVENT_TABLE()
53 //////////////////////////////////////////////////////////////////////////////
54 // Standalone functions
56 bool EditRecord(wxWindow *parent, bool editable, Barry::Contact &rec)
58 ContactEditDlg edit(parent, rec, editable);
59 return edit.ShowModal() == wxID_OK;
62 bool EditRecord(wxWindow *parent, bool editable, Barry::Bookmark &rec)
64 return false;
67 bool EditRecord(wxWindow *parent, bool editable, Barry::Calendar &rec)
69 return false;
72 bool EditRecord(wxWindow *parent, bool editable, Barry::CalendarAll &rec)
74 return false;
77 bool EditRecord(wxWindow *parent, bool editable, Barry::ContentStore &rec)
79 return false;
82 bool EditRecord(wxWindow *parent, bool editable, Barry::Folder &rec)
84 return false;
87 bool EditRecord(wxWindow *parent, bool editable, Barry::Memo &rec)
89 return false;
92 bool EditRecord(wxWindow *parent, bool editable, Barry::Message &rec)
94 return false;
97 bool EditRecord(wxWindow *parent, bool editable, Barry::CallLog &rec)
99 return false;
102 bool EditRecord(wxWindow *parent, bool editable, Barry::PINMessage &rec)
104 return false;
107 bool EditRecord(wxWindow *parent, bool editable, Barry::SavedMessage &rec)
109 return false;
112 bool EditRecord(wxWindow *parent, bool editable, Barry::ServiceBook &rec)
114 return false;
117 bool EditRecord(wxWindow *parent, bool editable, Barry::Sms &rec)
119 return false;
122 bool EditRecord(wxWindow *parent, bool editable, Barry::Task &rec)
124 return false;
127 bool EditRecord(wxWindow *parent, bool editable, Barry::Timezone &rec)
129 return false;
132 bool EditRecord(wxWindow *parent, bool editable, Barry::HandheldAgent &rec)
134 return false;
138 //////////////////////////////////////////////////////////////////////////////
139 // GUIDesktopConnector
141 bool GUIDesktopConnector::PasswordPrompt(const Barry::BadPassword &bp,
142 std::string &password_result)
144 // create prompt based on exception data
145 ostringstream oss;
146 oss << "Please enter device password: ("
147 << bp.remaining_tries()
148 << " tries remaining)";
149 wxString prompt(oss.str().c_str(), wxConvUTF8);
151 // ask user for device password
152 wxString pass = wxGetPasswordFromUser(prompt,
153 _T("Device Password"), _T(""), m_parent);
155 password_result = pass.utf8_str();
157 // assume that a blank password means the user wishes to quit...
158 // wxWidgets doesn't seem to handle this very well?
159 return password_result.size() > 0;
162 //////////////////////////////////////////////////////////////////////////////
163 // DBDataCache
165 DBDataCache::DBDataCache(DataCache::IndexType index, const Barry::DBData &raw)
166 : DataCache(index, raw.GetUniqueId())
167 , m_raw(raw)
171 bool DBDataCache::Edit(wxWindow *parent, bool editable)
173 return false;
176 std::string DBDataCache::GetDescription() const
178 return "raw data";
182 //////////////////////////////////////////////////////////////////////////////
183 // DBCache
185 DBCache::DBCache(ThreadableDesktop &tdesktop, const std::string &dbname)
186 : m_tdesktop(tdesktop)
187 , m_dbname(dbname)
189 // lock the desktop
190 DesktopInstancePtr dip = m_tdesktop.Get();
192 // grab the DBID
193 m_dbid = dip->Desktop().GetDBID(m_dbname);
195 // load the record state table
196 dip->Desktop().GetRecordStateTable(m_dbid, m_state);
198 // load all records
199 AllRecordParser ap(*this, *this);
200 RecordStateTable::StateMapType::iterator i = m_state.StateMap.begin();
201 for( ; i != m_state.StateMap.end(); ++i ) {
202 m_index = i->second.Index; // save for the callback
203 dip->Desktop().GetRecord(m_dbid, m_index, ap);
206 // sort the list of records by description
207 m_records.sort();
210 DBCache::~DBCache()
214 DBCache::iterator DBCache::Get(int list_offset)
216 iterator i = begin();
217 for( ; i != end() && list_offset; ++i, list_offset-- )
219 return i;
222 DBCache::const_iterator DBCache::Get(int list_offset) const
224 const_iterator i = begin();
225 for( ; i != end() && list_offset; ++i, list_offset-- )
227 return i;
230 int DBCache::GetIndex(iterator record) const
232 iterator i = const_cast<DBCache*> (this)->begin();
233 iterator e = const_cast<DBCache*> (this)->end();
234 for( int index = 0; i != e; ++i, index++ ) {
235 if( i == record )
236 return index;
238 return -1;
241 int DBCache::GetIndex(const_iterator record) const
243 const_iterator i = begin();
244 for( int index = 0; i != end(); ++i, index++ ) {
245 if( i == record )
246 return index;
248 return -1;
251 DBCache::iterator DBCache::Add(wxWindow *parent, iterator copy_record)
253 DataCachePtr p;
255 #undef HANDLE_BUILDER
256 #define HANDLE_BUILDER(tname) \
257 if( m_dbname == Barry::tname::GetDBName() ) { \
258 Barry::tname rec; \
259 if( copy_record != end() ) { \
260 RecordCache<Barry::tname> *rc = dynamic_cast<RecordCache<Barry::tname>* > (copy_record->get()); \
261 if( rc ) { \
262 rec = rc->GetRecord(); \
265 p.reset( new RecordCache<Barry::tname>(0, rec) ); \
267 ALL_KNOWN_BUILDER_TYPES
269 // anything else is not addable or buildable
270 if( !p.get() ) {
271 return end();
274 if( p->Edit(parent, true) ) {
275 // see if this record has a builder
276 Barry::Builder *bp = dynamic_cast<Barry::Builder*> (p.get());
277 if( !bp ) {
278 return end();
281 // give record a new UniqueID
282 uint32_t record_id = m_state.MakeNewRecordId();
283 cout << "New recordID generated: 0x" << hex << record_id << endl;
284 p->SetIds(p->GetStateIndex(), record_id);
286 // add record to device
287 DesktopInstancePtr dip = m_tdesktop.Get();
288 Barry::Mode::Desktop &desktop = dip->Desktop();
289 desktop.AddRecord(m_dbid, *bp);
291 // update our copy of the record state table from device
292 desktop.GetRecordStateTable(m_dbid, m_state);
293 cout << m_state << endl;
295 // find our new record_id in list, to find the state index
296 IndexType new_index;
297 if( !m_state.GetIndex(record_id, &new_index) ) {
298 throw std::logic_error("Need to reconnect for adding a record?");
301 // update new state_index in the data cache record
302 p->SetIds(new_index, record_id);
304 // add DataCachePtr to our own cache list
305 m_records.push_front(p);
307 // return iterator pointing to new record
308 return begin();
310 else {
311 return end();
315 bool DBCache::Edit(wxWindow *parent, iterator record)
317 if( record == end() )
318 return false;
320 if( (*record)->Edit(parent, true) && (*record)->IsBuildable() ) {
321 // see if this record has a builder
322 Barry::Builder *bp = dynamic_cast<Barry::Builder*> ((*record).get());
323 if( !bp )
324 return false;
326 cout << "Changing device record with index: 0x" << hex << (*record)->GetStateIndex() << endl;
327 cout << m_state << endl;
328 // update the device with new record data
329 DesktopInstancePtr dip = m_tdesktop.Get();
330 Barry::Mode::Desktop &desktop = dip->Desktop();
331 desktop.SetRecord(m_dbid, (*record)->GetStateIndex(), *bp);
333 return true;
335 else {
336 return false;
340 bool DBCache::Delete(wxWindow *parent, iterator record)
342 if( record == end() )
343 return false;
345 // prompt user with Yes / No message
346 wxString desc((*record)->GetDescription().c_str(), wxConvUTF8);
347 int choice = wxMessageBox(_T("Delete record: ") + desc + _T("?"),
348 _T("Record Delete"), wxYES_NO | wxICON_QUESTION, parent);
350 // if no, return false
351 if( choice != wxYES )
352 return false;
354 cout << "Deleting device record with index: 0x" << hex << (*record)->GetStateIndex() << endl;
355 cout << m_state << endl;
356 // delete record from device
357 DesktopInstancePtr dip = m_tdesktop.Get();
358 Barry::Mode::Desktop &desktop = dip->Desktop();
359 desktop.DeleteRecord(m_dbid, (*record)->GetStateIndex());
361 // remove record from cache list
362 m_records.erase(record);
363 return true;
366 // For Barry::AllRecordStore
367 #undef HANDLE_PARSER
368 #define HANDLE_PARSER(tname) \
369 void DBCache::operator() (const Barry::tname &rec) \
371 DataCachePtr p( new RecordCache<Barry::tname>(m_index, rec) ); \
372 m_records.push_front(p); \
374 ALL_KNOWN_PARSER_TYPES
376 // For Barry::Parser
377 void DBCache::ParseRecord(const Barry::DBData &data,
378 const Barry::IConverter *ic)
380 DataCachePtr p( new DBDataCache(m_index, data) );
381 m_records.push_front(p);
385 //////////////////////////////////////////////////////////////////////////////
386 // DBMap
388 DBMap::DBMap(ThreadableDesktop &tdesktop)
389 : m_tdesktop(tdesktop)
391 if( pthread_mutex_init(&m_map_mutex, NULL) ) {
392 throw Barry::Error("Failed to create map mutex");
396 DBMap::DBCachePtr DBMap::LoadDBCache(const std::string &dbname)
398 scoped_lock lock(m_map_mutex);
400 MapType::iterator i = m_map.find(dbname);
401 if( i != m_map.end() )
402 return i->second;
404 // do not unlock here, since we only want to load this
405 // data once, not provide a window for loading it twice
407 // not found, time to load it up
408 DBCachePtr p( new DBCache(m_tdesktop, dbname) );
409 m_map[dbname] = p;
410 return p;
413 DBMap::DBCachePtr DBMap::GetDBCache(const std::string &dbname)
415 scoped_lock lock(m_map_mutex);
417 MapType::iterator i = m_map.find(dbname);
418 if( i != m_map.end() )
419 return i->second;
421 return DBCachePtr();
424 //////////////////////////////////////////////////////////////////////////////
425 // BrowseMode
427 BrowseMode::BrowseMode(wxWindow *parent, const ProbeResult &device)
428 : m_parent(parent)
429 , m_buildable(false)
430 , m_show_all(false)
432 // create device identifying string
433 m_device_id_str = wxString(device.GetDisplayName().c_str(), wxConvUTF8);
436 // connect to the device
438 m_con.reset( new GUIDesktopConnector(m_parent, "", "utf-8", device) );
439 m_con->Reconnect(2);
440 m_tdesktop.reset( new ThreadableDesktop(*m_con) );
442 // keep our own copy, and sort by name for later
443 m_dbdb = m_con->GetDesktop().GetDBDB();
444 m_dbdb.SortByName();
446 CreateControls();
448 // create our DBMap and give it the threadable desktop,
449 // now that we're finished doing any desktop USB work
450 m_dbmap.reset( new DBMap(*m_tdesktop) );
453 // From here down, we assume that our constructor succeeds, with
454 // no exceptions!
457 // fire off a background thread to cache database records
458 // in advance... if it fails, don't worry about it
459 m_abort_flag = false;
460 int ret = pthread_create(&m_cache_thread, NULL,
461 &BrowseMode::FillCacheThread, this);
462 if( ret != 0 )
463 m_abort_flag = true; // no need to join later
465 // connect ourselves to the parent's event handling chain
466 // do this last, so that we are guaranteed our destructor
467 // will run, in case of exceptions
468 m_parent->PushEventHandler(this);
471 BrowseMode::~BrowseMode()
473 // unhook that event handler!
474 m_parent->PopEventHandler();
476 // make sure the cache thread is finished before we destroy it :-)
477 if( !m_abort_flag ) {
478 m_abort_flag = true;
479 void *junk;
480 pthread_join(m_cache_thread, &junk);
484 std::string& GetDBName(Barry::DatabaseDatabase::Database &db)
486 return db.Name;
489 void BrowseMode::CreateControls()
491 m_top_sizer.reset( new wxBoxSizer(wxVERTICAL) );
493 // make space for the main header, which is not part of our
494 // work area
495 m_top_sizer->AddSpacer(MAIN_HEADER_OFFSET);
499 // add list boxes to main area, the list_sizer
502 wxStaticBoxSizer *list_sizer = new wxStaticBoxSizer(wxHORIZONTAL,
503 m_parent, m_device_id_str);
505 // add database listctrl
506 m_dbdb_list.reset (new wxListCtrl(m_parent, BrowseMode_DBDBList,
507 wxDefaultPosition, wxDefaultSize,
508 wxLC_REPORT | wxLC_SINGLE_SEL) ); //| wxLC_VRULES
509 // int max_db_width = GetMaxWidth(m_dbdb_list.get(),
510 // m_dbdb.Databases.begin(), m_dbdb.Databases.end(),
511 // &GetDBName);
512 list_sizer->Add( m_dbdb_list.get(), 4, wxEXPAND | wxALL, 4 );
514 // add the record listctrl
515 m_record_list.reset(new wxListCtrl(m_parent, BrowseMode_RecordList,
516 wxDefaultPosition, wxDefaultSize,
517 wxLC_REPORT | wxLC_SINGLE_SEL) ); //| wxLC_VRULES
518 list_sizer->Add( m_record_list.get(), 5, wxEXPAND | wxALL, 4 );
520 // add list sizer to top sizer
521 m_top_sizer->Add( list_sizer, 1, wxEXPAND | wxALL, 4 );
524 // add "show all" checkbox
527 m_show_all_checkbox.reset( new wxCheckBox(m_parent,
528 BrowseMode_ShowAllCheckbox,
529 _T("Show All Databases"),
530 wxDefaultPosition, wxDefaultSize,
531 wxCHK_2STATE) );
532 m_top_sizer->Add( m_show_all_checkbox.get(), 0, wxEXPAND | wxALL, 4 );
533 m_show_all_checkbox->SetValue(m_show_all);
536 // bottom buttons
539 // add bottom buttons - these go in the bottom FOOTER area
540 // so their heights must be fixed to MAIN_HEADER_OFFSET
541 // minus a border of 5px top and bottom
542 wxSize footer(-1, MAIN_HEADER_OFFSET - 5 - 5);
543 wxBoxSizer *buttons = new wxBoxSizer(wxHORIZONTAL);
544 m_add_record_button.reset( new wxButton(m_parent,
545 BrowseMode_AddRecordButton, _T("Add..."),
546 wxDefaultPosition, footer) );
547 m_copy_record_button.reset( new wxButton(m_parent,
548 BrowseMode_CopyRecordButton, _T("Copy..."),
549 wxDefaultPosition, footer) );
550 m_edit_record_button.reset( new wxButton(m_parent,
551 BrowseMode_EditRecordButton, _T("Edit..."),
552 wxDefaultPosition, footer));
553 m_delete_record_button.reset( new wxButton(m_parent,
554 BrowseMode_DeleteRecordButton, _T("Delete..."),
555 wxDefaultPosition, footer) );
556 buttons->Add(m_add_record_button.get(), 0, wxRIGHT, 5);
557 buttons->Add(m_copy_record_button.get(), 0, wxRIGHT, 5);
558 buttons->Add(m_edit_record_button.get(), 0, wxRIGHT, 5);
559 buttons->Add(m_delete_record_button.get(), 0, wxRIGHT, 5);
560 m_top_sizer->Add(buttons, 0, wxALL | wxALIGN_RIGHT, 5);
563 // recalc size of children and add columns
565 wxSize client_size = m_parent->GetClientSize();
566 m_top_sizer->SetDimension(0, 0,
567 client_size.GetWidth(), client_size.GetHeight());
569 // m_dbdb_list
570 wxSize dbdb_size = m_dbdb_list->GetClientSize();
571 int scroll_width = wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
572 int size = dbdb_size.GetWidth() - scroll_width;
573 m_dbdb_list->InsertColumn(0, _T("Databases"), wxLIST_FORMAT_LEFT,
574 size * 0.80);
575 m_dbdb_list->InsertColumn(1, _T("Count"), wxLIST_FORMAT_LEFT,
576 size * 0.20 + scroll_width); // add back the scroll width
577 // so it doesn't look half-baked when
578 // there is no scroll bar
581 // m_record_list
582 wxSize record_size = m_record_list->GetClientSize();
583 m_record_list->InsertColumn(0, _T("Record Description"),
584 wxLIST_FORMAT_LEFT, record_size.GetWidth());
588 // add data
590 FillDBDBList();
593 // attempt to re-select the devices as we last saw them
594 ReselectDevices(m_device_set->String2Subset(wxGetApp().GetGlobalConfig().GetKey("SelectedDevices")));
595 UpdateButtons();
600 int BrowseMode::GUItoDBDBIndex(int gui_index)
602 if( m_show_all )
603 return gui_index;
605 DatabaseDatabase::DatabaseArrayType::const_iterator
606 i = m_dbdb.Databases.begin(), e = m_dbdb.Databases.end();
607 for( int index = 0; i != e; ++i, index++ ) {
608 // only bump index on the parsable databases
609 if( !m_show_all && !IsParsable(i->Name) )
610 continue;
612 if( !gui_index )
613 return index;
615 gui_index--;
618 // error
619 return -1;
622 void BrowseMode::FillDBDBList()
624 // start fresh
625 m_dbdb_list->DeleteAllItems();
627 DatabaseDatabase::DatabaseArrayType::const_iterator
628 i = m_dbdb.Databases.begin(), e = m_dbdb.Databases.end();
629 for( int index = 0; i != e; ++i, index++ ) {
630 // Only show parsable databases, depending on GUI
631 if( !m_show_all && !IsParsable(i->Name) )
632 continue;
634 // Database Name
635 wxString text(i->Name.c_str(), wxConvUTF8);
636 long item = m_dbdb_list->InsertItem(index, text);
638 // Record Count
639 ostringstream oss;
640 oss << dec << i->RecordCount;
641 text = wxString(oss.str().c_str(), wxConvUTF8);
642 m_dbdb_list->SetItem(item, 1, text);
645 UpdateButtons();
648 void BrowseMode::FillRecordList(const std::string &dbname)
650 try {
652 // start fresh
653 m_record_list->DeleteAllItems();
655 // grab our DB
656 DBMap::DBCachePtr db = m_dbmap->LoadDBCache(dbname);
658 // cycle through the cache, and insert the descriptions
659 // given for each record
660 DBCache::const_iterator b = db->begin(), e = db->end();
661 for( int index = 0; b != e; ++b, index++ ) {
662 wxString text((*b)->GetDescription().c_str(), wxConvUTF8);
663 //long item =
664 m_record_list->InsertItem(index, text);
667 } catch( Barry::Error &be ) {
668 cerr << be.what() << endl;
672 void BrowseMode::UpdateButtons()
674 int selected_count = m_record_list->GetSelectedItemCount();
676 // can only add if we have a builder for this record type
677 m_add_record_button->Enable(m_buildable);
678 // can only copy or edit if we have a builder, and only 1 is selected
679 m_copy_record_button->Enable(m_buildable && selected_count == 1);
680 m_edit_record_button->Enable(m_buildable && selected_count == 1);
681 // can only delete if something is selected
682 m_delete_record_button->Enable(selected_count > 0);
685 void BrowseMode::FillCache()
687 // cycle through the dbdb and load all Parsable databases
688 DatabaseDatabase::DatabaseArrayType::const_iterator
689 i = m_dbdb.Databases.begin(), e = m_dbdb.Databases.end();
690 for( ; i != e; ++i ) {
691 if( IsParsable(i->Name) ) try {
692 m_dbmap->LoadDBCache(i->Name);
693 } catch( Barry::Error &be ) {
694 cerr << be.what() << endl;
697 if( m_abort_flag )
698 break;
701 // finished
702 m_abort_flag = true;
705 void* BrowseMode::FillCacheThread(void *bobj)
707 BrowseMode *bm = (BrowseMode*) bobj;
708 bm->FillCache();
709 return NULL;
712 void BrowseMode::OnDBDBListSelChange(wxListEvent &event)
714 wxBusyCursor wait;
715 int index = GUItoDBDBIndex(event.GetIndex());
716 m_current_dbname = m_dbdb.Databases.at(index).Name;
717 m_buildable = ::IsBuildable(m_current_dbname);
718 m_current_record_item = -1;
720 FillRecordList(m_current_dbname);
721 UpdateButtons();
724 void BrowseMode::OnRecordListSelChange(wxListEvent &event)
726 // grab the cache for the current database... Get is ok here,
727 // since the cache is already loaded by the main db list
728 DBMap::DBCachePtr p = m_dbmap->GetDBCache(m_current_dbname);
729 if( !p.get() )
730 return;
732 // grab the record list index
733 m_current_record_item = event.GetIndex();
734 // m_current_record_item = m_record_list->GetNextItem(
735 // m_current_record_item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
737 UpdateButtons();
740 void BrowseMode::OnRecordListActivated(wxListEvent &event)
742 wxCommandEvent ce;
743 OnEditRecord(ce);
746 void BrowseMode::OnShowAll(wxCommandEvent &event)
748 m_show_all = !m_show_all;
749 FillDBDBList();
752 void BrowseMode::OnAddRecord(wxCommandEvent &event)
754 // grab the cache for the current database... Get is ok here,
755 // since the cache is already loaded by the main db list
756 DBMap::DBCachePtr p = m_dbmap->GetDBCache(m_current_dbname);
757 if( !p.get() )
758 return;
760 DBCache::iterator i = p->Add(m_parent, p->end());
761 if( i != p->end() ) {
762 wxString text((*i)->GetDescription().c_str(), wxConvUTF8);
764 // insert new record in same spot as DBCache has it
765 m_current_record_item = p->GetIndex(i);
766 m_record_list->InsertItem(m_current_record_item, text);
770 void BrowseMode::OnCopyRecord(wxCommandEvent &event)
772 // grab the cache for the current database... Get is ok here,
773 // since the cache is already loaded by the main db list
774 DBMap::DBCachePtr p = m_dbmap->GetDBCache(m_current_dbname);
775 if( !p.get() )
776 return;
778 DBCache::iterator source = p->Get(m_current_record_item);
779 DBCache::iterator i = p->Add(m_parent, source);
780 if( i != p->end() ) {
781 wxString text((*i)->GetDescription().c_str(), wxConvUTF8);
783 // insert new record in same spot as DBCache has it
784 m_current_record_item = p->GetIndex(i);
785 m_record_list->InsertItem(m_current_record_item, text);
789 void BrowseMode::OnEditRecord(wxCommandEvent &event)
791 // grab the cache for the current database... Get is ok here,
792 // since the cache is already loaded by the main db list
793 DBMap::DBCachePtr p = m_dbmap->GetDBCache(m_current_dbname);
794 if( !p.get() )
795 return;
797 DBCache::iterator i = p->Get(m_current_record_item);
798 if( p->Edit(m_parent, i) ) {
799 wxString text((*i)->GetDescription().c_str(), wxConvUTF8);
800 m_record_list->SetItem(m_current_record_item, 0, text);
804 void BrowseMode::OnDeleteRecord(wxCommandEvent &event)
806 // grab the cache for the current database... Get is ok here,
807 // since the cache is already loaded by the main db list
808 DBMap::DBCachePtr p = m_dbmap->GetDBCache(m_current_dbname);
809 if( !p.get() )
810 return;
812 DBCache::iterator i = p->Get(m_current_record_item);
813 if( p->Delete(m_parent, i) ) {
814 m_record_list->DeleteItem(m_current_record_item);