public void RemoveSharedStore(ZPushAccount account, GABUser shareUser) { // Find the store Logger.Instance.Trace(this, "Request to remove shared store: {0} - {1}", account, shareUser.UserName); ZPushAccount share = account.FindSharedAccount(shareUser.UserName); if (share == null) { Logger.Instance.Warning(this, "Shared store not found: {0} - {1}", account, shareUser.UserName); return; } Logger.Instance.Trace(this, "Removing shared store: {0} - {1}", account, share); try { string path = share.Account.BackingFilePath; ThisAddIn.Instance.Stores.RemoveStore(share.Account.Store); // Clean up the .ost // TODO: this always fails /*if (path != null && path.EndsWith(".ost")) * { * Logger.Instance.Trace(this, "Removing .ost: {0}", path); * * System.IO.File.Delete(path); * }*/ } catch (Exception e) { Logger.Instance.Error(this, "Error removing shared store: {0}: {1}", share, e); } }
public StoreTreeNode(SharedFoldersManager folders, GABHandler gab, GABUser user, string text, Dictionary <BackendId, SharedFolder> currentFolders) : base(text) { this._initialShares = currentFolders; this._feature = folders.Feature; this._gab = gab; this._user = user; // Create an empty current state. When loading the nodes, the shares will be added. This has the benefit of // cleaning up automatically any obsolote shares. this._currentShares = new Dictionary <BackendId, SharedFolder>(); ChildLoader = new UserFolderLoader(this, folders, user); ChildLoader.ReloadOnCloseOpen = true; HasCheckBox = false; // TODO: better icons, better way of handling this ImageIndex = user == GABUser.USER_PUBLIC ? 0 : 11; // Reloader _reloader = new KAnimator(); _reloader.Animation = Properties.Resources.TreeLoading; _reloader.Visible = false; _reloader.Click += (s, e) => { ChildLoader.Reload(); }; Control = _reloader; }
public string FindSendAsAddress(ZPushAccount zpush, GABUser user) { GABHandler handler = FeatureGAB.FindGABForAccount(zpush); if (handler != null && handler.Contacts != null) { // Look for the email address. If found, use the account associated with the GAB using (ISearch <IContactItem> search = handler.Contacts.Search <IContactItem>()) { search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, user.UserName); using (IContactItem result = search.SearchOne()) { Logger.Instance.Trace(this, "GAB Search for send-as {0}: {1}", zpush, result); if (result != null) { // Try resolving by email Logger.Instance.Trace(this, "Resolving send-as by email address {0}: {1}", user.UserName, result.Email1Address); return(result.Email1Address); } } } } else { Logger.Instance.Warning(this, "GAB handler not found for account: {0}", zpush); } Logger.Instance.Warning(this, "Unable to resolve send-as: {0}", user.UserName); return(null); }
public void SetCurrentShares(GABUser store, ICollection <SharedFolder> shares, CancellationToken?cancel = null) { using (ZPushWebServiceDevice deviceService = _connection.DeviceService) { deviceService.Execute(new AdditionalFolderSetListRequest(store, shares)); } }
public void OpenShare(ZPushAccount account, GABUser store, bool showReminders) { _shares.Add(new Share() { account = account, store = store, showReminders = showReminders }); }
private void AddUserFolders(GABUser user, Dictionary <BackendId, SharedFolder> currentShares, bool select) { if (user == null) { return; } // If the user is already fetched, reuse the node StoreTreeNode node; if (!_userFolders.TryGetValue(user, out node)) { if (!user.HasFullName) { // Try to fill in the full name user = gabLookup.LookupExact(user.UserName); } // Add the node node = new StoreTreeNode(_folders, gabLookup.GAB, user, user.DisplayName, currentShares ?? new Dictionary <BackendId, SharedFolder>()); node.DirtyChanged += UserSharesChanged; _userFolders.Add(user, node); kTreeFolders.RootNodes.Add(node); } if (select) { FocusNode(node); } }
private string GetSecondLine(GABUser item) { if (item is NotFoundGABUser) { return(NotFoundText); } else { return(item.EmailAddress); } }
public void RemoveSharesForStore(GABUser store, ICollection <SharedFolder> removed) { foreach (SharedFolder folder in removed) { if (folder.SyncId != null) { _account.SetSendAsAddress(folder.SyncId, null); } _account.SetSendAsAddress(folder.BackendId, null); } }
/// <summary> /// Sets all shares for the specified store. /// </summary> public void SetSharesForStore(GABUser store, ICollection <SharedFolder> shares, CancellationToken?cancel) { // Make sure reminders are updated as soon as possible UpdateReminders(shares); _api.SetCurrentShares(store, shares, cancel); // Commit changes if (_query != null) { _query.Commit(); } }
protected override void OnDrawItem(DrawItemEventArgs e) { GABUser item = (GABUser)e.Item; // Draw the background if (e.State == DrawItemState.Selected) { // If the item is selected, we don't want the separating border to get selected too. // So draw the normal background in the border area Rectangle rect = e.Bounds; rect.Y = rect.Bottom - BorderPadding.Vertical - BorderThickness; rect.Height = BorderPadding.Vertical + BorderThickness; new System.Windows.Forms.DrawItemEventArgs(e.Graphics, e.Font, rect, e.Index, DrawItemState.None).DrawBackground(); // And the selected background in the item area. rect.Y = e.Bounds.Y; rect.Height = e.Bounds.Height - BorderPadding.Vertical - BorderThickness; new System.Windows.Forms.DrawItemEventArgs(e.Graphics, e.Font, rect, e.Index, DrawItemState.Selected).DrawBackground(); } else { e.DrawBackground(); } // Get the sizes Size nameSize = TextRenderer.MeasureText(e.Graphics, item.FullName, Font); Size loginSize = TextRenderer.MeasureText(e.Graphics, item.UserName, Font); Size emailSize = TextRenderer.MeasureText(e.Graphics, item.EmailAddress, Font); // Draw the full name top-left Point pt = e.Bounds.TopLeft(); pt.Y += ItemPadding.Top; pt.X += ItemPadding.Left; TextRenderer.DrawText(e.Graphics, item.FullName, Font, pt, e.ForeColor); // Draw the username top-right pt.X = e.Bounds.Right - loginSize.Width - ItemPadding.Right; TextRenderer.DrawText(e.Graphics, item.UserName, Font, pt, e.ForeColor); // Draw the email below pt.Y += Math.Max(nameSize.Height, loginSize.Height) + NameSpacing.Height; pt.X = e.Bounds.X + ItemPadding.Left; TextRenderer.DrawText(e.Graphics, GetSecondLine(item), Font, pt, e.ForeColor); // Draw a separator line if (e.Index < DisplayItemCount - 1) { int lineY = e.Bounds.Bottom - 1 - BorderThickness - BorderPadding.Bottom; e.Graphics.DrawLine(Pens.LightGray, BorderPadding.Left, lineY, e.Bounds.Width - BorderPadding.Right, lineY); } }
public StoreTreeNode(SharedFoldersManager folders, GABHandler gab, GABUser user, string sendAsAddress, string text, Dictionary <BackendId, SharedFolder> currentFolders, bool isShared, bool showRemindersWholeStore) : base(text) { this._initialShares = currentFolders; // Patch in send as address foreach (SharedFolder share in _initialShares.Values) { if (string.IsNullOrWhiteSpace(share.SendAsAddress)) { share.SendAsAddress = sendAsAddress; } } this._feature = folders.Feature; this._featureSendAs = ThisAddIn.Instance.GetFeature <FeatureSendAs>(); this._account = folders.Account; this._gab = gab; this._user = user; this._sendAsAddress = sendAsAddress; this.IsReadOnly = false; this._isShared = isShared; // Create an empty current state. When loading the nodes, the shares will be added. This has the benefit of // cleaning up automatically any obsolote shares. this._currentShares = new Dictionary <BackendId, SharedFolder>(); ChildLoader = new UserFolderLoader(this, folders, user); ChildLoader.ReloadOnCloseOpen = true; // Can only open the whole store if it's supported and there's an email address, as that's needed to open it // However, if it's already opened, we can remove it without the email address HasCheckBox = folders.SupportsWholeStore && (!string.IsNullOrWhiteSpace(user.EmailAddress) || isShared); ApplyReadOnly(this, IsReadOnly); // TODO: better icons, better way of handling this ImageIndex = user == GABUser.USER_PUBLIC ? 0 : 11; // Reloader _reloader = new KAnimator(); _reloader.Animation = Properties.Resources.TreeLoading; _reloader.Visible = false; _reloader.Click += (s, e) => { ChildLoader.Reload(); }; Control = _reloader; // Set up sharing WantShare = isShared; ShowRemindersInitial = showRemindersWholeStore; ShowReminders = ShowRemindersInitial; }
protected override void OnMeasureItem(MeasureItemEventArgs e) { GABUser item = (GABUser)e.Item; Size nameSize = TextRenderer.MeasureText(e.Graphics, item.FullName, Font); Size loginSize = TextRenderer.MeasureText(e.Graphics, item.UserName, Font); Size emailSize = TextRenderer.MeasureText(e.Graphics, GetSecondLine(item), Font); e.ItemWidth = Math.Max(emailSize.Width, nameSize.Width + loginSize.Width + NameSpacing.Width) + ItemPadding.Horizontal; e.ItemHeight = emailSize.Height + Math.Max(nameSize.Height, loginSize.Height) + ItemPadding.Vertical + NameSpacing.Height + BorderThickness + BorderPadding.Vertical; }
internal IRecipient FindSendAsSender(ZPushAccount zpush, GABUser user) { // First try a simple resolve, this will work if the username is unique IRecipient recip = ThisAddIn.Instance.ResolveRecipient(user.UserName); if (recip != null) { // If it's resolved, we're good. Otherwise dispose and continue if (recip.IsResolved) { return(recip); } else { recip.Dispose(); } } // Search through GAB to find the user if (GABLookup) { GABHandler handler = FeatureGAB.FindGABForAccount(zpush); if (handler != null && handler.Contacts != null) { // Look for the email address. If found, use the account associated with the GAB using (ISearch <IContactItem> search = handler.Contacts.Search <IContactItem>()) { search.AddField("urn:schemas:contacts:customerid").SetOperation(SearchOperation.Equal, user.UserName); using (IContactItem result = search.SearchOne()) { if (result != null) { // Try resolving by email return(ThisAddIn.Instance.ResolveRecipient(result.Email1Address)); } } } } } return(null); }
public ICollection <AvailableFolder> GetUserFolders(GABUser user) { using (ZPushWebServiceInfo infoService = _connection.InfoService) { // Fetch raw folder list List <AvailableFolder> folders = infoService.Execute(new ListUserFoldersRequest(user.UserName)); // Construct the tree Dictionary <SyncId, AvailableFolder> foldersByServerId = folders.ToDictionary((x) => x.ServerId); List <AvailableFolder> rootNodes = new List <AvailableFolder>(); foreach (AvailableFolder folder in folders) { AvailableFolder parent; // Add to root nodes or parent if (folder.ParentId.IsNone) { rootNodes.Add(folder); parent = null; } else if (!foldersByServerId.ContainsKey(folder.ParentId)) { // Ignore the node if the parent is not available Logger.Instance.Warning(this, "Missing parent node: {0}", folder.ParentId); continue; } else { parent = foldersByServerId[folder.ParentId]; parent.Children.Add(folder); } folder.FixupSoap(parent, user); } // Return the root nodes return(rootNodes); } }
/// <summary> /// Sets all shares for the specified store. /// </summary> public void SetSharesForStore(GABUser store, ICollection <SharedFolder> shares, CancellationToken?cancel) { // Make sure reminders are updated as soon as possible UpdateReminders(shares); // Store the send-as addresses foreach (SharedFolder share in shares) { if (share.CanSendAs) { _account.SetSendAsAddress(share.BackendId, share.FlagSendAsOwner ? share.SendAsAddress : null); } } // Update the shares _api.SetCurrentShares(store, shares, cancel); // Commit changes if (_query != null) { _query.Commit(); } }
private void AddUserFolders(GABUser user, ZPushAccount wholeStore, Dictionary <BackendId, SharedFolder> currentShares, bool select) { if (user == null) { return; } // If the user is already fetched, reuse the node StoreTreeNode node; if (!_userFolders.TryGetValue(user, out node)) { if (!user.HasFullName) { // Try to fill in the full name user = gabLookup.LookupExact(user.UserName); } string sendAsAddress = _featureSendAs?.FindSendAsAddress(_account, user); // Add the node node = new StoreTreeNode(_folders, gabLookup.GAB, user, sendAsAddress, user.DisplayName, currentShares ?? new Dictionary <BackendId, SharedFolder>(), wholeStore != null, wholeStore?.ShowReminders == true); node.DirtyChanged += UserSharesChanged; node.CheckStateChanged += WholeStoreShareChanged; _userFolders.Add(user, node); kTreeFolders.RootNodes.Add(node); } if (select) { FocusNode(node, !_folders.SupportsWholeStore); } }
protected override void OnSelectedItemChanged() { _selectedUser = (GABUser)SelectedItem?.Item; // If the tab key was used to select, the user wants to click open SelectedUserChanged?.Invoke(this, new SelectedUserEventArgs(_selectedUser, GetCommitSource() != CommitSource.KeyTab)); }
public ICollection <AvailableFolder> GetStoreFolders(GABUser store) { return(_api.GetUserFolders(store)); }
/// <summary> /// Fixes up data not serialised by soap. /// </summary> public void FixupSoap(AvailableFolder parent, GABUser store) { this.Parent = parent; this.Store = store; }
public AdditionalFolderSetListRequest(GABUser store, ICollection <SharedFolder> shares) { Parameters.Add("store", store.UserName); Parameters.Add("folders", shares); }
public UserFolderLoader(StoreTreeNode parent, SharedFoldersManager folders, GABUser user) : base(parent) { this._folders = folders; this.User = user; }
public SelectedUserEventArgs(GABUser selectedUser, bool isChosen) { this.SelectedUser = selectedUser; this.IsChosen = isChosen; }
public void OpenShare(ZPushAccount account, GABUser store) { _shares.Add(new KeyValuePair <ZPushAccount, GABUser>(account, store)); }
protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); _selectedUser = string.IsNullOrEmpty(Text) ? null : new GABUser(Text); SelectedUserChanged?.Invoke(this, new SelectedUserEventArgs(_selectedUser, false)); }