void CCompareResultsDlg::OnCompareSynchronize() { if (m_bOriginalDBReadOnly) return; CGeneralMsgBox gmb; CString cs_temp, cs_title; // Initialize set GTUSet setGTU; // First check database if (!m_pcore0->GetUniqueGTUValidated() && !m_pcore0->InitialiseGTU(setGTU)) { // Database is not unique to start with - tell user to validate it first cs_title.LoadString(IDS_SYNCHFAILED); cs_temp.Format(IDS_DBHASDUPLICATES, m_pcore0->GetCurFile().c_str()); gmb.MessageBox(cs_temp, cs_title, MB_ICONEXCLAMATION); return; } setGTU.clear(); // Don't need it anymore - so clear it now DWORD_PTR dwItemData = m_LCResults.GetItemData(m_LCResults.GetRow()); st_CompareData *pst_data = GetCompareData(dwItemData); ASSERT(pst_data != NULL); ProcessFunction(SYNCH, pst_data); }
void CompareDlg::OnSyncItemsWithCurrentDB(wxCommandEvent& evt) { if (m_currentCore->IsReadOnly()) { wxMessageBox(_("Current safe was opened read-only"), _("Synchronize"), wxOK|wxICON_INFORMATION, this); return; } GTUSet setGTU; if (!m_currentCore->GetUniqueGTUValidated() && !m_currentCore->InitialiseGTU(setGTU)) { // Database is not unique to start with - tell user to validate it first wxMessageBox(wxString::Format(_("The database:\n\n%ls\n\nhas duplicate entries with the same group/title/user combination. Please fix by validating database."), m_currentCore->GetCurFile().c_str()), _("Synchronization failed"), wxOK|wxICON_EXCLAMATION, this); return; } setGTU.clear(); // Don't need it anymore - so clear it now //we only synchronize these fields const CItemData::FieldType syncFields[] = { CItemData::PASSWORD, CItemData::URL, CItemData::EMAIL, CItemData::AUTOTYPE, CItemData::NOTES, CItemData::PWHIST, CItemData::POLICY, CItemData::CTIME, CItemData::PMTIME, CItemData::ATIME, CItemData::XTIME, CItemData::RMTIME, CItemData::XTIME_INT, CItemData::RUNCMD, CItemData::DCA, CItemData::PROTECTED, CItemData::SYMBOLS, CItemData::SHIFTDCA, }; FieldSet userSelection(syncFields, syncFields + WXSIZEOF(syncFields)); //let the user choose which fields to synchronize FieldSelectionDlg dlg(this, NULL, 0, //no fields are left unselected by default NULL, 0, //But no fields are mandatory userSelection, _T("Synchronize")); if (dlg.ShowModal() == wxID_OK) { wxCHECK_RET(userSelection.size() > 0, wxT("User did not select any fields to sync?")); ContextMenuData* menuContext = reinterpret_cast<ContextMenuData*>(evt.GetClientData()); wxCHECK_RET(menuContext, wxT("No menu context available")); //start with the selected items wxArrayInt syncIndexes(menuContext->selectedItems); if (evt.GetId() == ID_SYNC_ALL_ITEMS_WITH_CURRENT_DB) { //add all items to the sync Index list syncIndexes.Empty(); const size_t numIndexes = menuContext->cdata->data.size(); syncIndexes.Alloc(numIndexes); for(size_t i = 0; i < numIndexes; ++i) syncIndexes.Add(i); } else { wxCHECK_RET(evt.GetId() == ID_SYNC_SELECTED_ITEMS_WITH_CURRENT_DB, wxT("Sync menu id is neither for all nor for selected items")); } //use a wxScopedPtr to clean up the heap object if we trip on any of the wxCHECK_RETs below MultiCommandsPtr pMultiCmds(MultiCommands::Create(m_currentCore)); for (size_t idx = 0; idx < syncIndexes.Count(); ++idx) { ItemListIter fromPos = m_otherCore->Find(menuContext->cdata->data[syncIndexes[idx]].uuid1); wxCHECK_RET(fromPos != m_otherCore->GetEntryEndIter(), wxT("Could not find sync item in other db")); const CItemData *pfromEntry = &fromPos->second; ItemListIter toPos = m_currentCore->Find(menuContext->cdata->data[syncIndexes[idx]].uuid0); wxCHECK_RET(toPos != m_currentCore->GetEntryEndIter(), wxT("Could not find sync item in current db")); CItemData *ptoEntry = &toPos->second; CItemData updtEntry(*ptoEntry); //create a copy of the "to" object, with only the to-be-sync'ed fields changed bool bUpdated(false); for (FieldSet::const_iterator itr = userSelection.begin(); itr != userSelection.end(); ++itr) { const StringX sxValue = pfromEntry->GetFieldValue(*itr); if (sxValue != updtEntry.GetFieldValue(*itr)) { bUpdated = true; updtEntry.SetFieldValue(*itr, sxValue); } } //Don't change anything yet. Just keep track of the differences. if (bUpdated) { updtEntry.SetStatus(CItemData::ES_MODIFIED); Command *pcmd = EditEntryCommand::Create(m_currentCore, *ptoEntry, updtEntry); pMultiCmds->Add(pcmd); } } //Update all or nothing. And there's no way of knowing if any of the sub-commands //inside MultiCommands failed if (pMultiCmds->GetSize() > 0) { m_currentCore->Execute(pMultiCmds.release()); ComparisonGridTable* ptable = wxDynamicCast(menuContext->cdata->grid->GetTable(), ComparisonGridTable); wxCHECK_RET(ptable, wxT("Could not find ComparisonGridTable derived object in comparison grid")); const ComparisonGridTable& table = *ptable; wxCHECK_RET(menuContext->cdata == m_conflicts, wxT("Sync happened in unexpected grid")); for( size_t idx = 0; idx < syncIndexes.Count(); ++idx) { //refresh every even-numbered row table.RefreshRow(syncIndexes[idx]*2); } } } }