/// <summary> /// Determines whether this instance can a shell context show menu, given the specified selected file list. /// </summary> /// <returns> /// <c>true</c> if this instance should show a shell context menu for the specified file list; otherwise, <c>false</c>. /// </returns> protected override bool CanShowMenu() { string[] TargetFiles = SelectedItemPaths.ToArray(); // start a connection here. P4EXPProgram.Connect(TargetFiles[0]); RepoStorage store = null; try { store = P4EXPProgram.getRepoStorage(TargetFiles[0]); } catch (Exception e) { FileLogger.LogException(Properties.Resources.FileLogger_MenuExtension, e); return(true); } lock (store) { try { loginVisible = !store.connected || !store.loggedIn; if (!store.connected) { // notify of disconnected in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionNotConnectedMenuItem; setConnectionImage = Properties.Resources.disconnected; outsideRootMenuitemVisible = false; startP4VMenuitemVisible = true; return(true); } if (store.rep.Connection.Client == null || (store.rep.Connection.Client.Root == null && store.roots.Count < 1)) { // notify of missing P4CLIENT in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_NoWorkspaceSet; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; return(true); } if (!store.IsUnderClientRoot(TargetFiles[0])) { // notify of outside root in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_OutsideRoot; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; return(true); } Repository rep = store.rep; // checking here for connected and directory change bool stale = false; bool checkedout = false; bool indepot = false; bool notindepot = false; bool haverev = false; bool cancheckout = false; bool folderselect = false; //check if each target file is a directory and if so, convert // convert to =+/... List <string> selectedItems = new List <string>(); commandFiles = new List <FileMetaData>(); foreach (string path in TargetFiles) { string pathToAdd = path; FileAttributes attr = System.IO.File.GetAttributes(path); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) { pathToAdd += @"\..."; notindepot = true; folderselect = true; FileMetaData folder = new FileMetaData(); folder.LocalPath = new LocalPath(pathToAdd); commandFiles.Add(folder); pathToAdd = pathToAdd.Replace(@"\...", @"\*"); selectedItems.Add(pathToAdd); } else { selectedItems.Add(pathToAdd); FileMetaData file = new FileMetaData(); file.LocalPath = new LocalPath(pathToAdd); commandFiles.Add(file); } } FileSpec[] fs = new FileSpec[TargetFiles.Length]; fs = FileSpec.LocalSpecArray(selectedItems.ToArray()); // TODO might need to set an fstat -m limit here if (store.loggedIn) { IList <FileMetaData> fmd = P4EXPProgram.GetFileMetaData(fs); // if no P4Exception is caught by attempting to get // FileMetaData, remove the initial menu items and // add the rest of the menu items and seperators if (fmd != null) { moreMenuitemVisible = true; foreach (FileMetaData d in fmd) { if (stale && checkedout && indepot && notindepot && haverev && cancheckout) { break; } if (d == null || (d.HaveRev == -1 && d.Action != FileAction.Add)) { notindepot = true; break; } if (d.HaveRev < d.HeadRev) { stale = true; } if (d.Action != FileAction.None) { checkedout = true; } if (d.IsInDepot) { indepot = true; } if (d.IsInClient) { haverev = true; } if ((d.Action == FileAction.None) && d.IsInClient && d.IsInDepot) { cancheckout = true; } } } else { outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } if (stale || folderselect) { getLatestMenuitemVisible = true; subSeperator1Visible = true; } if (checkedout || folderselect) { submitMenuitemVisible = true; } if (cancheckout || folderselect) { checkoutMenuitemVisible = true; subSeperator2Visible = true; } if (notindepot || folderselect) { addMenuitemVisible = true; } if (cancheckout) { deleteMenuitemVisible = true; subSeperator2Visible = true; } if (checkedout || folderselect || notindepot) { subSeperator2Visible = true; if (!notindepot) { if (!folderselect) { revertMenuitemVisible = true; } revertUnchangedMenuitemVisible = true; subSeperator3Visible = true; } } // only on single selection of file if (TargetFiles.Length == 1) { if (!folderselect && haverev) { diffAgainstHaveMenuitemVisible = true; diffAgainstMenuitemVisible = true; fileHistoryMenuitemVisible = true; timeLapseViewMenuitemVisible = true; propertiesMenuitemVisible = true; showInP4VMenuitemVisible = true; subSeperator4Visible = true; } else { if (!folderselect) { diffAgainstMenuitemVisible = true; } // don't allow folder history on the // workspace root if (TargetFiles[0] != store.rep.Connection.Client.Root) { fileHistoryMenuitemVisible = true; } subSeperator4Visible = true; } } if ((haverev && !(checkedout)) || folderselect) { removeFromWorkspaceMenuitemVisible = true; } if (fmd != null || folderselect || notindepot) { refreshFileStateMenuitemVisible = true; subSeperator5Visible = true; pendingChangesMenuitemVisible = true; moreMenuitemVisible = true; } } } catch (P4Exception ex) { // Leaving this for now. It looks like it is a possible redundant check // of more efficient if (ex.ErrorCode == P4ClientError.MsgDb_NotUnderRoot) // below. It also looks like it would never be hit based on the string // "outside root". Adding a message dialog for the case that this ever gets // hit. if (ex.ErrorLevel == ErrorSeverity.E_FATAL && ex.Message == "outside root") { Message message = new Message("CanShowMenu() P4Exception", ex.Message); message.ShowDialog(); setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_OutsideRoot; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } if (P4EXPProgram.IsLoginException(ex.ErrorCode)) { P4EXPProgram.Login(TargetFiles[0]); if (store.rep.Connection.Status == ConnectionStatus.Disconnected) { // notify of disconnected in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionNotConnectedMenuItem; setConnectionImage = Properties.Resources.disconnected; outsideRootMenuitemVisible = false; startP4VMenuitemVisible = true; } } else if (ex.ErrorCode == P4ClientError.MsgServer_PasswordExpired) { store.loggedIn = false; loginVisible = true; string message = ex.Message; Message dlg = new Message(Properties.Resources.MessageDlg_PasswordExpired, message); dlg.ShowDialog(); } else if (ex.ErrorCode == P4ClientError.MsgDm_NeedClient) { // second happens when P4CLIENT is not set 841226339 setConnection = Properties.Resources.ContextMenus_SetConnectionConnectedMenuItem; setConnectionImage = Properties.Resources.connected_with_issues; outside = Properties.Resources.ContextMenus_NoWorkspaceSet; outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } else if (ex.ErrorCode == P4ClientError.MsgDb_NotUnderRoot) { // do nothing, this is a file not under workspace root. // just return, the context menu is already set to show this. outsideRootMenuitemVisible = true; startP4VMenuitemVisible = true; } if (P4EXPProgram.showP4Exception()) { string message = ex.Message + "\n" + ex.StackTrace + "\n" + ex.TargetSite.Name; Message dlg = new Message(Properties.Resources.MessageDlg_P4Exception, message); dlg.ShowDialog(); } FileLogger.LogException(Properties.Resources.FileLogger_BuildContextMenu, ex); return(true); } catch (Exception ex) { // TODO: is this catching a login request? // this does not appear to be something that will be // part of a P4ClientError. Leaving it in for now. Unsure if it // would ever be hit. Adding a message dialog for the case that // this ever gets hit. if (ex.Message.Contains("requires")) { Message message = new Message("CanShowMenu() Exception", ex.Message); message.ShowDialog(); P4EXPProgram.Connect(TargetFiles[0]); } if (store.rep != null && store.rep.Connection.Status == ConnectionStatus.Disconnected) { // notify of disconnected in top menu item setConnection = Properties.Resources.ContextMenus_SetConnectionNotConnectedMenuItem; setConnectionImage = Properties.Resources.disconnected; outsideRootMenuitemVisible = false; startP4VMenuitemVisible = true; } if (P4EXPProgram.showException()) { string message = ex.Message + "\n" + ex.StackTrace + "\n" + ex.TargetSite.Name; Message dlg = new Message(Properties.Resources.MessageDlg_Exception, message); dlg.ShowDialog(); } FileLogger.LogException(Properties.Resources.FileLogger_BuildContextMenu, ex); return(true); } } // We always show the menu for now. This will still return true, // but individual menu items may be made invisible return(true); }