void ModuleBasicsPageEvtHandler::OnListTreeSelChanged(wxTreeEvent& event) { TDEBUG_ENTER("ModuleBasicsPageEvtHandler::OnListTreeSelChanged"); if (myIgnoreChange) { myIgnoreChange = false; return; } wxArrayTreeItemIds sel; int selCount = static_cast<int>(myParent->GetTreeCtrl()->GetSelections(sel)); if (selCount == 1) { wxTreeItemData* thisdata = myParent->GetTreeCtrl()->GetItemData(sel[0]); if (thisdata) { CRepoNode* thisnode = ((ModuleBasicsPageTreeItemData*) thisdata)->m_Node; // If it's a module then just the name goes in the module box. // If it's a directory or file then we need to traverse the entire // tree back up to the module collecting all the names on the way... // unless the CRepoNode class can do that for us when it creates // the node in the first place.... that'd be good... switch (thisnode->GetType()) { case kNodeModule: { CRepoNodeModule* modulenode = (CRepoNodeModule*) (thisnode); myParent->GetModuleCombo()->SetValue(wxText(modulenode->c_str())); myParent->GetModule() = wxAscii(myParent->GetModuleCombo()->GetValue().c_str()); myParent->UpdateModule(); } break; case kNodeDirectory: { CRepoNodeDirectory* directorynode = (CRepoNodeDirectory*) (thisnode); myParent->GetModuleCombo()->SetValue(wxText(directorynode->c_str())); myParent->GetModule() = wxAscii(myParent->GetModuleCombo()->GetValue().c_str()); myParent->UpdateModule(); } break; case kNodeFile: { CRepoNodeFile* filenode = (CRepoNodeFile*) (thisnode); myParent->GetModuleCombo()->SetValue(wxText(filenode->c_str())); myParent->GetModule() = wxAscii(myParent->GetModuleCombo()->GetValue().c_str()); myParent->UpdateModule(); } break; default: break; } } } }
// Size event handler void ExtSplitterWindow::OnSize(wxSizeEvent& e) { TDEBUG_ENTER("ExtSplitterWindow::OnSize"); if (m_RightSashPos >= 0) { SetSashPosition(e.GetSize().GetHeight() - m_RightSashPos); } e.Skip(); }
void ModuleBasicsPageEvtHandler::OnListTreeRightClick(wxTreeEvent& event) { TDEBUG_ENTER("ModuleBasicsPageEvtHandler::OnListTreeRightClick"); if (!myParent->GetTreeCtrl()->IsSelected(event.GetItem()) && GetAsyncKeyState(VK_APPS) >= 0) { myParent->GetTreeCtrl()->SelectItem(event.GetItem()); } }
void BuildIgnoredList(std::vector<std::string> & ignlist, const std::string& path, DWORD *timeStamp, FileChangeParams *fcp) { TDEBUG_ENTER("BuildIgnoredList"); bool doUpdate = false; std::string ignPath(path); ignPath = EnsureTrailingDelimiter(ignPath); ignPath += ".cvsignore"; FileChangeParams myFcp; if (fcp) myFcp = GetFileChangeParams(ignPath); // Update default ignored list BuildDefaultIgnoredList(); if (timeStamp) { if ((*timeStamp != defIgnoreListTimeStamp) || (*timeStamp == 0)) doUpdate = true; } else { doUpdate = true; } // check directory ignored file if (fcp) { if ((fcp->IsNull()) || (*fcp != myFcp)) { doUpdate = true; } } else { doUpdate = true; } // Do we have to update if (doUpdate) { ignlist.clear(); ignlist = defIgnoredList; // TODO: read $CVSROOT/CVSROOT/cvsignore // Read .cvsignore from current directory ReadIgnoredFile(ignPath, ignlist); if (fcp) *fcp = myFcp; if (timeStamp) *timeStamp = defIgnoreListTimeStamp; } }
bool RunExternalMerge(std::string fileMine, std::string fileYours, DirectoryGroups& dirGroups, std::string fileOlder) { TDEBUG_ENTER("RunExternalMerge"); TDEBUG_TRACE("File mine: " << fileMine); TDEBUG_TRACE("File yours: " << fileYours); bool bResult = true; bool again = false; std::string command; std::string externalApp; std::string externalParams; // Perform merge, waiting for it to finish if (fileOlder.empty()) { externalParams = dirGroups.GetStringPreference("External Merge2 Params"); std::map<std::string, std::string> params; params["mine"] = fileMine; params["yours"] = fileYours; externalParams = ReplaceParams(externalParams, params); } else externalParams = dirGroups.GetStringPreference("External Merge3 Params"); do { externalApp = GetExternalApplication("Merge", dirGroups, again); again = false; if (externalApp.empty()) { goto Cleanup; } command = "\"" + externalApp + "\" " + externalParams; if (!LaunchCommand(command, true)) { DoMessageDialog(0, wxString(_("Failed to launch external merge application")) + wxString(wxT("\n")) + wxString(wxText(command))); again = true; } } while (again); bResult = true; Cleanup: return bResult; }
// Split horizontally bool ExtSplitterWindow::SplitHorizontally(wxWindow *window1, wxWindow *window2, int sashPosition) { TDEBUG_ENTER("ExtSplitterWindow::SplitHorizontally"); bool b = wxSplitterWindow::SplitHorizontally(window1, window2, sashPosition); if (sashPosition < 0) m_RightSashPos = -sashPosition; else m_RightSashPos = -1; return b; }
std::string GetExternalApplication(const char* appType, const DirectoryGroups& dirGroups, bool forceQuery) { TDEBUG_ENTER("GetExternalApplication"); std::string regName; wxString dialogTitle; if (stricmp(appType, "Diff") == 0) { regName = "External Diff Application"; dialogTitle = _("Choose external diff application"); } else if (stricmp(appType, "Merge") == 0) { regName = "External Merge Application"; dialogTitle = _("Choose external merge application"); } else { return ""; } TDEBUG_TRACE("RegKey: " << regName); std::string externalApp = dirGroups.GetStringPreference(regName); if (externalApp.empty() || (externalApp == "?")) // Module preference not set, use global externalApp = GetStringPreference(regName); TDEBUG_TRACE("App: " << externalApp); // Only ask the user once for external diff application if (externalApp.empty() && !forceQuery) return externalApp; // A question mark signals to ask the user if (externalApp == "?" || forceQuery) { do { if (externalApp == "?") externalApp = ""; externalApp = DoOpenFileDialog(0, dialogTitle, externalApp, wxString(_("Executables")) + wxString(wxT(" (*.exe)|*.exe"))); } while (!(externalApp.empty() || FileExists(externalApp.c_str()))); // Always set global preference SetStringPreferenceRootModule(regName, externalApp, ""); } return externalApp; }
std::string CVSStatus::CVSRepositoryForPath(std::string path) { TDEBUG_ENTER("CVSStatus::CVSRepositoryForPath"); TDEBUG_TRACE(" path: '" << path << "')"); // We must be a directory with a CVS dir path = GetDirectoryPart(path); path = EnsureTrailingDelimiter(path); if (!CVSDirectoryHere(path)) return ""; std::string rootFile = path + "CVS/Repository"; std::ifstream in(rootFile.c_str(), std::ios::in); if (!in.good()) return ""; std::string repository; std::getline(in, repository); // Apparently, the path in CVS/Repository may be either absolute or relative. // So if it is absolute, we hack it to be relative. TDEBUG_TRACE(" Repository is '" << repository << "')"); if (repository[0] == '/' || (repository.length() > 2 && repository[1] == ':')) { CVSRoot cvsroot(CVSRootForPath(path)); std::string root = cvsroot.GetDirectory(); TDEBUG_TRACE(" Root is '" << root << "')"); unsigned int i = 0; // Find out how many leading chars match while (i < root.length() && i < repository.length()) { if (root[i] == repository[i] || (root[i] == '\\' && repository[i] == '/') || (root[i] == '/' && repository[i] == '\\')) { i++; continue; } else { break; } } // Also kill final slash if (repository[i] == '/' || repository[i] == '\\') ++i; repository = repository.substr(i); } return repository; }
bool RunExternalDiff(std::string filename1, std::string filename2, DirectoryGroups& dirGroups, std::string filename3) { TDEBUG_ENTER("RunExternalDiff"); TDEBUG_TRACE("File 1: " << filename1); TDEBUG_TRACE("File 2: " << filename2); bool bResult = true; bool again = false; std::string command; std::string externalApp; std::string externalParams; // Perform diff, waiting for it to finish if (filename3.empty()) { externalParams = dirGroups.GetStringPreference("External Diff2 Params"); std::map<std::string, std::string> params; params["1"] = filename1; params["2"] = filename2; externalParams = ReplaceParams(externalParams, params); } else externalParams = dirGroups.GetStringPreference("External Diff3 Params"); do { externalApp = GetExternalApplication("Diff", dirGroups, again); again = false; if (externalApp.empty()) return false; command = "\"" + externalApp + "\" " + externalParams; if (!LaunchCommand(command, true)) { DoMessageDialog(0, wxString(_("Failed to launch external diff application")) + wxString(wxT("\n")) + wxString(wxText(command))); again = true; } } while (again); return true; }
// mostly the cvs one... static bool unmodified(const struct stat & sb, const char* ts) { TDEBUG_ENTER("unmodified"); struct tm tmbuf; char timebuf[30]; char* cp; struct tm *tm_p; struct tm local_tm; /* We want to use the same timestamp format as is stored in the st_mtime. For unix (and NT I think) this *must* be universal time (UT), so that files don't appear to be modified merely because the timezone has changed. For VMS, or hopefully other systems where gmtime returns NULL, the modification time is stored in local time, and therefore it is not possible tcause st_mtime to be out of sync by changing the timezone. */ tm_p = gmtime_r(&sb.st_mtime, &tmbuf); if (tm_p) { memcpy (&local_tm, tm_p, sizeof (local_tm)); cp = asctime_r(&local_tm, timebuf); /* copy in the modify time */ } else cp = ctime_r(&sb.st_mtime, timebuf); if (!cp) return true; cp[24] = 0; #if defined(_MSC_VER) || defined(__GNUWIN32__) /* Work around non-standard asctime() and ctime() in MS VC++ and mingw These return '01' instead of ' 1' for the day of the month. */ if ( (strlen(ts) > 8) && ((cp[8] == '0' && ts[8] == ' ') || (cp[8] == ' ' && ts[8] == '0')) ) { cp[8] = ts[8]; } #endif TDEBUG_TRACE("Timestamp: " << ts); TDEBUG_TRACE("Filetime : " << cp); return strcmp(cp, ts) == 0; }
unsigned int CAnnotationList::AddAnnotation(const std::string& line) { TDEBUG_ENTER("AddAnnotation"); TDEBUG_TRACE("Line: " << line); annotationList.push_back(new CAnnotation(this, static_cast<unsigned int>(annotationList.size() + 1), line)); tm& date = annotationList[annotationList.size() - 1]->Date(); TDEBUG_TRACE("Date: " << date.tm_mday << "-" << date.tm_mon << "-" << date.tm_year << " " << date.tm_hour << ":" << date.tm_min); time_t itemDate = mktime(&date); if (minDate == 0 || itemDate < minDate) minDate = itemDate; if (maxDate == 0 || itemDate > maxDate) maxDate = itemDate; dateMap[itemDate] = 1; return static_cast<unsigned int>(annotationList.size()); }
void AnnotateDialog::Populate(CAnnotationList* annotationList) { TDEBUG_ENTER("AnnotateDialog::Populate"); myAnnotations = annotationList; unsigned int annotateCount = annotationList->AnnotationCount(); myListCtrl->SetItemCount(annotateCount); // Create the line color array delete[] myLineColors; myLineColors = new wxColour[annotateCount]; for (unsigned int i = 0; i < annotateCount; i++) { CAnnotation* item = (*annotationList)[i]; TDEBUG_TRACE("Item " << i << ": " << asctime(&(item->Date())) << item->Text()); item->SetData(&myLineColors[i]); } ApplySort(); }
void ModuleBasicsPageEvtHandler::OnListTreeExpand(wxTreeEvent& event) { TDEBUG_ENTER("ModuleBasicsPageEvtHandler::OnListTreeExpand"); wxTreeItemId openingitem = event.GetItem(); long c = 0; // Cookie wxTreeItemData* thisdata = myParent->GetTreeCtrl()->GetItemData(openingitem); if (thisdata) { wxTreeItemId childitem = myParent->GetTreeCtrl()->GetFirstChild(openingitem, c); wxTreeItemData* childdata = myParent->GetTreeCtrl()->GetItemData(childitem); CRepoNode* childnode = ((ModuleBasicsPageTreeItemData*) childdata)->m_Node; if (childnode->GetType() == kNodeRubbish) { myParent->GetTreeCtrl()->DeleteChildren(openingitem); myParent->GetTreeCtrl()->SelectItem(openingitem); myParent->GoBrowse(openingitem); } } }
// Build default ignored list void BuildDefaultIgnoredList() { TDEBUG_ENTER("BuildDefaultIgnoredList"); CSHelper csHelper(myCriticalSection, true); std::string userCvsIgnoreFile; GetHomeDirectory(userCvsIgnoreFile); userCvsIgnoreFile = EnsureTrailingDelimiter(userCvsIgnoreFile) + ".cvsignore"; FileChangeParams myFcp = GetFileChangeParams(userCvsIgnoreFile); // Update every dwUpdateIgnoredListInterval seconds if (GetTickCount() > defIgnoreListTimeStamp + 1000 * dwUpdateIgnoredListInterval) { DoUpdateIgnoredList(); fcpCvsignore = myFcp; } // Update if .cvsignore in home dir has changed else if (fcpCvsignore != myFcp) { DoUpdateIgnoredList(); fcpCvsignore = myFcp; } }
bool GetHomeDirectory(std::string& HomeDirectory) { TDEBUG_ENTER("GetHomeDirectory"); std::string home(""); bool SuccessValue; // We usually recalculate home every time - so ignore the // value in the registry. The user can turn that off though! if (!GetBooleanPreference("Always Recalculate Home")) home = GetStringPreference("HOME"); if (home.empty() || !IsDirectory(home.c_str())) SuccessValue = GetCalculatedHomeDirectory(home); else SuccessValue = true; TDEBUG_TRACE("Home directory is " << home); SuccessValue = (SuccessValue && !home.empty() && IsDirectory(home.c_str())); if (SuccessValue) HomeDirectory = home; return SuccessValue; }
EntnodeData *Entries_SetVisited(const char* path, EntnodeMap& entries, const char* name, const struct stat& finfo, bool isDir, bool isReadOnly, bool isMissing, const std::vector<std::string>* ignlist) { TDEBUG_ENTER("Entries_SetVisited"); bool isCvs = false; std::string lookupName; if (isDir) { TDEBUG_TRACE("Is dir"); EntnodeDir *adata = new EntnodeDir(path, name); ENTNODE anode(adata); adata->UnRef(); lookupName = anode.Data()->GetName(); EntnodeMap::iterator it = entries.find(lookupName); isCvs = it != entries.end(); if (!isCvs) entries[lookupName] = anode; } else { TDEBUG_TRACE("Is no dir"); EntnodeFile *adata = new EntnodeFile(path, name); ENTNODE anode(adata); adata->UnRef(); lookupName = anode.Data()->GetName(); EntnodeMap::iterator it = entries.find(lookupName); isCvs = it != entries.end(); if (!isCvs) entries[lookupName] = anode; } const ENTNODE & theNode = entries[lookupName]; EntnodeData *data = ((ENTNODE *)&theNode)->Data(); data->SetVisited(true); if (!isCvs) { data->SetUnknown(true); if (ignlist && MatchIgnoredList(name, *ignlist) || finfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) data->SetIgnored(true); // the dir may have some cvs informations in it, despite the fact // that it is not referenced by the parent directory, so try // to figure it. if (!data->IsIgnored()) { std::string cvsFile = path; cvsFile = EnsureTrailingDelimiter(cvsFile); cvsFile += name; cvsFile = EnsureTrailingDelimiter(cvsFile); cvsFile += "CVS"; struct stat sb; TDEBUG_TRACE("Before stat"); if (stat(cvsFile.c_str(), &sb) != -1 && S_ISDIR(sb.st_mode)) { data->SetUnknown(false); } TDEBUG_TRACE("After stat"); } } data->SetReadOnly(isReadOnly); data->SetMissing(isMissing); if (isDir) { if (data->IsIgnored()) data->SetDesc(_("Ignored Folder")); else if (data->IsUnknown()) data->SetDesc(_("Non-CVS Folder")); else data->SetDesc(_("Folder")); } else if (!isMissing) { const char* ts = data->GetTS(); TDEBUG_TRACE("Timestamp: " << (ts == 0 ? "NULL" : ts)); // Revision "0" means "added" if (ts == 0) { data->SetUnmodified(true); } else if (strcmp(data->GetVN(), "0") == 0) { data->SetAdded(true); // Added files are always modified data->SetUnmodified(false); } else { data->SetUnmodified(unmodified(finfo, ts)); } const char* ts_conflict = data->GetConflict(); if (ts_conflict == 0) data->SetNeedsMerge(false); else data->SetNeedsMerge(unmodified(finfo,ts_conflict)); data->SetLocked((finfo.st_mode & S_IWRITE) == 0); const char* info = 0; if (data->IsIgnored()) { data->SetDesc(_("Ignored")); } else if (data->IsUnknown()) { data->SetDesc(_("Non-CVS File")); } else if (data->NeedsMerge()) { data->SetDesc(_("Conflict")); } else if ((info = data->GetOption()) != 0 && strcmp(info, "-kb") == 0) { data->SetDesc(data->IsUnmodified() ? _("Binary") : _("Mod. Binary")); } else { data->SetDesc(data->IsUnmodified() ? _("File") : _("Mod. File")); } } return data; }
/* Read the entries file into a list, hashing on the file name. UPDATE_DIR is the name of the current directory, for use in error messages, or NULL if not known (that is, noone has gotten around to updating the caller to pass in the information). */ bool Entries_Open(EntnodeMap& entries, const char* fullpath, FileChangeParams* fcp) { TDEBUG_ENTER("Entries_Open"); std::string cvsdir(fullpath); cvsdir = EnsureTrailingDelimiter(cvsdir); cvsdir += "CVS"; cvsdir = EnsureTrailingDelimiter(cvsdir); if (fcp) { FileChangeParams myFcp = GetFileChangeParams(cvsdir + "Entries"); if ((!(fcp->IsNull())) && (myFcp == *fcp)) { return true; } *fcp = myFcp; } entries.clear(); unsigned long sizeextra = 0; FILE* fpinx = fopen((cvsdir + "Entries.Extra").c_str(), "r"); if (fpinx) { FileChangeParams myFcp = GetFileChangeParams(cvsdir + "Entries.Extra"); sizeextra = myFcp.dwFileSizeLow; } FILE* fpin = fopen((cvsdir + "Entries").c_str(), "r"); if (!fpin) { if (fpinx) fclose (fpinx); return false; } // Read contents of CVS/Rename into a set for easy lookup std::ifstream cvsRename((cvsdir + "Rename").c_str()); std::set<std::string> renameEntries; while (cvsRename.good()) { std::string file; // Each entry is // newname // (blank) // newname // oldname // We are only interested in the new name. std::getline(cvsRename, file); file = ExtractLastPart(file); renameEntries.insert(file); for (int i = 0; i < 3; ++i) std::getline(cvsRename, file); } EntnodeData* ent; char* extrabuf = 0; size_t lenreadx; if (fpinx && (sizeextra > 0)) { extrabuf = (char*) malloc((sizeextra*2)+10); fseek(fpinx, 0, SEEK_SET); lenreadx = fread(extrabuf, sizeof(char), (sizeextra*2)+9, fpinx); *(extrabuf+lenreadx) = '\0'; if (!feof(fpinx)) { // could not read the whole file for some reason... free(extrabuf); extrabuf = 0; } } while ((ent = fgetentent(fpin, extrabuf, fullpath, 0, sizeextra)) != 0) { ENTNODE newnode(ent); ent->UnRef(); std::string name = newnode.Data()->GetName(); EntnodeMap::iterator it = entries.find(name); if (it != entries.end()) { _ASSERT(false); TDEBUG_TRACE("Warning : duplicated entry in the 'CVS/Entries' file in folder " << fullpath); } std::set<std::string>::iterator renameIter = renameEntries.find(name); ent->SetRenamed(renameIter != renameEntries.end()); entries[name] = newnode; } fclose (fpin); if (fpinx) fclose (fpinx); if (extrabuf) free (extrabuf); fpin = fopen((cvsdir + "Entries.log").c_str(), "r"); if (fpin) { char cmd; while ((ent = fgetentent(fpin, extrabuf, fullpath, &cmd, sizeextra)) != 0) { ENTNODE newnode(ent); ent->UnRef(); std::string name = newnode.Data()->GetName(); switch (cmd) { case 'A': entries[name] = newnode; break; case 'R': entries.erase(std::string(name)); break; default: /* Ignore unrecognized commands. */ TDEBUG_TRACE("Warning: Unrecognized command '" << cmd << "'"); break; } } fclose (fpin); } return true; }
void ModuleBasicsPageEvtHandler::OnListTreeContextMenu(wxContextMenuEvent& event) { TDEBUG_ENTER("ModuleBasicsPageEvtHandler::OnListTreeContextMenu"); }
// Parses a single line from a cvs annotate into its respective parts. An example of one line is: // 1.1 (frabcus 05-Jan-01): Building TortoiseCVS on Borland C++ Builder (version 4 or greater) bool CAnnotation::Parse(const std::string& line) { TDEBUG_ENTER("CAnnotation::Parse"); TDEBUG_TRACE("line: " << line); Clear(); if (line.empty()) return false; std::string token; std::string::size_type begin = 0; std::string::size_type end = 0; // revision number end = line.find(' ', begin); if (end == std::string::npos) return false; token = line.substr(begin, end); std::string::size_type tokenLength = token.length(); std::string num; for (;;) { end = token.find('.', begin); num = token.substr(begin, end - begin); revNum += atoi(num.c_str()); begin = end + 1; if (end == std::string::npos || end == tokenLength - 1) break; } // author begin = line.find('(', tokenLength); if (begin == std::string::npos) return false; ++begin; end = line.find(')', begin); if (end == std::string::npos) return false; end = line.rfind(' ', end); if (end == std::string::npos) return false; author = line.substr(begin, end - begin); // trim trailing whitespace from author author.erase(author.find_last_not_of(" ") + 1); // date begin = line.find_first_not_of(' ', end); if (begin == std::string::npos) return false; end = line.find(')', begin); if (end == std::string::npos) return false; token = line.substr(begin, end - begin); TDEBUG_TRACE("Date string: " << token); if (!datestring_to_tm(token.c_str(), &date)) return false; TDEBUG_TRACE("Datetime: " << asctime(&date)); // bugnumber bugnumber.clear(); // trim trailing whitespace from bugnumber bugnumber.erase(bugnumber.find_last_not_of(" ") + 1); // text begin = line.find_first_not_of("):", end); if (begin == std::string::npos) return false; text = line.substr(begin + 1); return true; }
EditorListDialog::EditorListDialog(wxWindow* parent, EditorListDialog::EditedFileList& editors) : ExtDialog(parent, -1, _("TortoiseCVS - List Editors"), wxDefaultPosition, wxDefaultSize, wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN), mySortCol(SORT_FILE), mySortAscending(true) { TDEBUG_ENTER("EditorListDialog::EditorListDialog"); SetIcon(wxIcon(wxT("A_TORTOISE"), wxBITMAP_TYPE_ICO_RESOURCE)); myEditedFiles = &editors; std::vector<std::string> tmp; EditedFileList::iterator it; // Add editors it = editors.begin(); while (it != editors.end()) { std::string s(it->myFilename); FindAndReplace<std::string>(s, "/", "\\"); it->myFilename = s; tmp.push_back(s); it++; } // Trim paths to sensible length ShortenPaths(tmp, myStub); // Maybe use dedicated colour later myEditColour = ColorRefToWxColour(GetIntegerPreference("Colour Updated Files")); FilenameText* label1 = new FilenameText(this, -1, _("Folder: %s"), wxText(RemoveTrailingDelimiter(myStub))); label1->SetWindowStyle(label1->GetWindowStyle() | wxST_NO_AUTORESIZE); myEditors = new EditorListListCtrl(this, this, EDITORLISTDLG_ID_EDITORS, myEditColour); myEditors->SetSortIndicator(mySortCol, mySortAscending); AddEditors(tmp, editors); myEditors->SetBestColumnWidth(0); myEditors->SetBestColumnWidth(1); myEditors->SetBestSize(wxDLG_UNIT(this, wxSize(150, 150)), wxDefaultSize); // OK button wxBoxSizer* sizerConfirm = new wxBoxSizer(wxHORIZONTAL); myOK = new wxButton(this, wxID_OK, _("Close")); myOK->SetDefault(); sizerConfirm->Add(myOK, 0, wxGROW | wxALL, 5); // Status bar myStatusBar = new wxStatusBar(this, -1); myStatusBar->SetStatusText(Printf(_("%d edited file(s)"), editors.size()).c_str()); // Main box with everything in it wxBoxSizer* sizerTop = new wxBoxSizer(wxVERTICAL); sizerTop->Add(label1, 0, wxGROW | wxALL, 3); sizerTop->Add(myEditors, 2, wxGROW | wxALL, 3); sizerTop->Add(sizerConfirm, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10); sizerTop->Add(myStatusBar, 0, wxGROW | wxALL, 0); // Overall dialog layout settings SetAutoLayout(TRUE); SetSizer(sizerTop); sizerTop->SetSizeHints(this); sizerTop->Fit(this); RestoreTortoiseDialogSize(this, "ListEditors"); SetTortoiseDialogPos(this, GetRemoteHandle()); RestoreTortoiseDialogState(this, "ListEditors"); }
// Sash pos changing event handler void ExtSplitterWindow::OnSashPosChanging(wxSplitterEvent& WXUNUSED(event)) { TDEBUG_ENTER("ExtSplitterWindow::OnSashPosChanged"); UpdateRightSashPosition(); }
ConflictListDialog::ConflictListDialog(wxWindow* parent, const std::vector<std::string>& files) : ExtDialog(parent, -1, _("TortoiseCVS - Resolve Conflicts"), wxDefaultPosition, wxDefaultSize, wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER | wxDEFAULT_DIALOG_STYLE | wxCLIP_CHILDREN) { TDEBUG_ENTER("ConflictListDialog::ConflictListDialog"); SetIcon(wxIcon(wxT("A_TORTOISE"), wxBITMAP_TYPE_ICO_RESOURCE)); std::vector<ItemData*> itemData; std::vector<std::string> tmp; std::vector<std::string>::const_iterator it; // Add files it = files.begin(); while (it != files.end()) { ItemData *data = new ItemData(); data->m_Filename = *it; data->m_Status = CVSStatus::STATUS_CONFLICT; itemData.push_back(data); tmp.push_back(*it); it++; } // Trim paths to sensible length ShortenPaths(tmp, myStub); wxStaticText* label2 = new ExtStaticText(this, -1, _( "CVS encountered conflicts when trying to merge your changes in the files below. Please merge your changes manually."), wxDefaultPosition, wxDLG_UNIT(this, wxSize(60, 15))); FilenameText* label1 = new FilenameText(this, -1, _("Folder: %s"), wxText(RemoveTrailingDelimiter(myStub))); label1->SetWindowStyle(label1->GetWindowStyle() | wxST_NO_AUTORESIZE); myFiles = new ExtListCtrl(this, CONFLICTLISTDLG_ID_FILES, wxDefaultPosition, wxDefaultSize, wxLC_REPORT | wxLC_ALIGN_LEFT); myFiles->PushEventHandler(new ListCtrlEventHandler(this)); myFiles->InsertColumn(0, _("Filename"), wxLIST_FORMAT_LEFT, 0); myFiles->InsertColumn(1, _("Format"), wxLIST_FORMAT_LEFT, 0); myFiles->InsertColumn(2, _("Status"), wxLIST_FORMAT_LEFT, 0); AddFiles(tmp, itemData); myFiles->SetBestColumnWidth(0); myFiles->SetBestColumnWidth(1); myFiles->SetBestColumnWidth(2); myFiles->SetBestSize(wxDLG_UNIT(this, wxSize(150, 150)), wxDefaultSize); wxStaticText* tip = new wxStaticText(this, -1, _("To resolve the conflicts, double or right click on the files above.")); tip->SetForegroundColour(SetForegroundColour(ColorRefToWxColour(GetIntegerPreference("Colour Tip Text")))); // OK/Cancel button wxBoxSizer* sizerConfirm = new wxBoxSizer(wxHORIZONTAL); myOK = new wxButton(this, wxID_OK, _("Close")); myOK->SetDefault(); sizerConfirm->Add(myOK, 0, wxGROW | wxALL, 5); // Status bar myStatusBar = new wxStatusBar(this, -1); myStatusBar->SetStatusText(Printf(_("%d file(s)"), files.size()).c_str()); // Main box with everything in it wxBoxSizer* sizerTop = new wxBoxSizer(wxVERTICAL); sizerTop->Add(label2, 0, wxGROW | wxALL, 3); sizerTop->Add(label1, 0, wxGROW | wxALL, 3); sizerTop->Add(myFiles, 2, wxGROW | wxALL, 3); sizerTop->Add(tip, 0, wxALIGN_LEFT | wxALL, 3); sizerTop->Add(sizerConfirm, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10); sizerTop->Add(myStatusBar, 0, wxGROW | wxALL, 0); // Overall dialog layout settings SetAutoLayout(TRUE); SetSizer(sizerTop); sizerTop->SetSizeHints(this); sizerTop->Fit(this); RestoreTortoiseDialogSize(this, "Conflict"); SetTortoiseDialogPos(this, GetRemoteHandle()); RestoreTortoiseDialogState(this, "Conflict"); }
// Get the annotation list CAnnotationList* AnnotateDialog::GetAnnotationList(wxWindow* parent) { TDEBUG_ENTER("GetAnnotationList"); wxBusyCursor(); // We do not want any progress dialog here CVSAction glue(parent); glue.SetCloseIfOK(true); glue.SetHideStdout(); wxString title = Printf(_("Annotate %s"), wxText(myFilename).c_str()); glue.SetProgressCaption(title); MakeArgs args; args.add_option("annotate"); // Avoid truncating user names args.add_option("-w"); args.add_option("30"); // Ought to be enough // If revision is given, specify it if (!myRevision.empty()) { args.add_option("-r"); args.add_option(myRevision); } // If we are working on a branch, specify the branch using -r else if (CVSStatus::HasStickyTag(myFilename)) { args.add_option("-r"); args.add_option(CVSStatus::GetStickyTag(myFilename)); } args.add_arg(ExtractLastPart(myFilename)); bool ok = glue.Command(StripLastPart(myFilename), args); if (!ok) { return 0; } std::string out = glue.GetOutputText(); #if 0 // Debugging std::ifstream in("C:\\cvs-log-output.txt"); out.clear(); while (true) { std::string line; std::getline(in, line); if (line.empty() && in.eof()) break; out += line; out += "\n"; } in.close(); #endif FindAndReplace<std::string>(out, "\r\n", "\n"); if (out.empty()) { wxString s(_("This file is new and has never been committed to the server or is an empty file on the server.")); s += wxT("\n\n"); s += wxText(myFilename); DoMessageDialog(0, s); return 0; } CAnnotationList* annotationList = new CAnnotationList(); std::stringstream ifs(out.c_str()); // Parsing the annotations while (true) { std::string line; if (!std::getline(ifs, line) && line.empty()) break; // We need to skip any text which comes before the actual annotations. A valid // annotation starts with the revision number, so we do a simple check to see if // the first character is a digit. This may need to be revised if this assumption // is not valid. if (!isdigit(line[0])) continue; annotationList->AddAnnotation(line); } return annotationList; }
AnnotateDialog::AnnotateDialog(wxWindow* parent, const std::string& filename, const std::string& rev) : ExtDialog(parent, -1, wxString(_("TortoiseCVS - Annotate")), wxDefaultPosition, wxSize(500,400), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMINIMIZE_BOX | wxMAXIMIZE_BOX), myFilename(filename), mySortCol(ANNOTATE_COL_LINE), mySortAscending(true), myLineColors(0), myHighlightType(HIGHLIGHT_BY_NONE), myRevision(rev), myGotLogMessages(false), myShowLogMessages(false), myFindDialog(0), myFoundLineIndex(std::numeric_limits<unsigned int>::max()) { TDEBUG_ENTER("AnnotateDialog"); SetIcon(wxIcon(wxT("A_TORTOISE"), wxBITMAP_TYPE_ICO_RESOURCE)); wxString sTitle = GetTitle(); sTitle += wxT(" "); sTitle += wxText(ExtractLastPart(filename)); if (!rev.empty()) { sTitle += wxT(" ("); sTitle += wxText(rev); sTitle += wxT(")"); } SetTitle(sTitle); myAnnotateCanvas = new AnnotateCanvas(this, -1, wxDefaultPosition, wxSize(10,10)); // List control myListCtrl = new AnnotateListCtrl(this, ANNOTATEDLG_ID_LISTCTRL, myAnnotateCanvas); int idx = 0; myListCtrl->InsertColumn(idx++, _("Line"), wxLIST_FORMAT_LEFT); myListCtrl->InsertColumn(idx++, _("Revision"), wxLIST_FORMAT_LEFT); myListCtrl->InsertColumn(idx++, _("Author"), wxLIST_FORMAT_LEFT); myListCtrl->InsertColumn(idx++, _("Date"), wxLIST_FORMAT_LEFT); #if 0 myListCtrl->InsertColumn(idx++, _("Bug Number"),wxLIST_FORMAT_LEFT); #endif myListCtrl->InsertColumn(idx++, _("Text"), wxLIST_FORMAT_LEFT); myFixedFont = wxSystemSettings::GetFont(wxSYS_ANSI_FIXED_FONT); wxBoxSizer *sizerAnnotate = new wxBoxSizer(wxHORIZONTAL); sizerAnnotate->Add(myListCtrl, 3, wxGROW | wxALL, 3); wxBoxSizer* sizerCanvas = new wxBoxSizer(wxVERTICAL); sizerCanvas->Add(myAnnotateCanvas, 1, wxGROW | wxTOP | wxBOTTOM, 21); sizerCanvas->Add(10, 19); sizerAnnotate->Add(sizerCanvas, 0, wxGROW); wxBoxSizer *sizer1 = new wxBoxSizer(wxVERTICAL); sizer1->Add(sizerAnnotate, 3, wxGROW | wxLEFT | wxUP | wxDOWN, 3); // OK button wxBoxSizer *sizerConfirm = new wxBoxSizer(wxHORIZONTAL); wxButton* buttonOK = new wxButton(this, wxID_OK, _("OK")); buttonOK->SetDefault(); sizerConfirm->Add(buttonOK, 0, wxALL, 5); wxButton* buttonSearch = new wxButton(this, wxID_FIND, _("&Find")); sizerConfirm->Add(buttonSearch, 0, wxALL, 5); SetDefaultItem(buttonOK); // Hidden Cancel button (only for making Esc close the dialog) wxButton* cancel = new wxButton(this, wxID_CANCEL, wxT("")); cancel->Hide(); // Status bar myStatusBar = new wxStatusBar(this, -1); // Main box with everything in it wxBoxSizer *sizerTop = new wxBoxSizer(wxVERTICAL); sizerTop->Add(sizer1, 2, wxGROW | wxALL, 3); sizerTop->Add(sizerConfirm, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, 10); sizerTop->Add(myStatusBar, 0, wxGROW | wxALL, 0); // Overall dialog layout settings SetAutoLayout(TRUE); SetSizer(sizerTop); sizerTop->SetSizeHints(this); sizerTop->Fit(this); RestoreTortoiseDialogSize(this, "Annotate", wxSize(500, 400)); SetTortoiseDialogPos(this, GetRemoteHandle()); RestoreTortoiseDialogState(this, "Annotate"); GetRegistryData(); UpdateStatusBar(); // Get column widths from registry (if not outdated) unsigned int numSavedColumns = static_cast<unsigned int>(myColumnWidths.size()); if (numSavedColumns == NUM_ANNOTATE_COL) { for (unsigned int i = 0; i < NUM_ANNOTATE_COL; ++i) { int colWidth = (i < numSavedColumns) ? myColumnWidths[i] : DEF_COLUMN_SIZE[i]; if (colWidth <= 0 || colWidth > MAX_COLUMN_SIZE) colWidth = DEF_COLUMN_SIZE[i]; myListCtrl->SetColumnWidth(i, wxDLG_UNIT_X(this, colWidth)); } } }
void ConflictListDialog::OnDblClick(wxListEvent& event) { TDEBUG_ENTER("ConflictListDialog::OnDblClick"); std::string file = ((ConflictListDialog::ItemData*) event.GetData())->m_Filename; LaunchTortoiseAct(false, CvsMergeConflictsVerb, file, "", GetHwnd()); }