blob: e6cecfe1b1a06c6a6b3ea89ab4cbd2c5c84c7eb6 [file] [log] [blame]
Alexandre Lision4dfcafc2015-08-20 12:43:23 -04001/*
Alexandre Lision9fe374b2016-01-06 10:17:31 -05002 * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
Alexandre Lision4dfcafc2015-08-20 12:43:23 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
Olivier Soldanod4311552017-11-20 15:09:53 -05004 * Author: Olivier Soldano <olivier.soldano@savoirfairelinux.com>
5 * Author: Anthony LĂ©onard <anthony.leonard@savoirfairelinux.com>
Alexandre Lision4dfcafc2015-08-20 12:43:23 -04006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#import "SmartViewVC.h"
23
24//Qt
25#import <QtMacExtras/qmacfunctions.h>
26#import <QPixmap>
27#import <QIdentityProxyModel>
28#import <QItemSelectionModel>
29
30//LRC
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040031#import <globalinstances.h>
Olivier Soldanod4311552017-11-20 15:09:53 -050032#import <api/newaccountmodel.h>
33#import <api/conversationmodel.h>
34#import <api/account.h>
35#import <api/contact.h>
36#import <api/contactmodel.h>
37#import <api/newcallmodel.h>
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040038
39#import "QNSTreeController.h"
40#import "delegates/ImageManipulationDelegate.h"
Alexandre Lision4e280d62015-09-09 15:56:30 -040041#import "views/HoverTableRowView.h"
Alexandre Lision61db3552015-10-22 19:12:52 -040042#import "PersonLinkerVC.h"
Alexandre Lision4baba4c2016-02-11 13:00:57 -050043#import "views/IconButton.h"
Olivier Soldanod4311552017-11-20 15:09:53 -050044#import "views/RingTableView.h"
Alexandre Lision4e280d62015-09-09 15:56:30 -040045#import "views/ContextualTableCellView.h"
Olivier Soldanod4311552017-11-20 15:09:53 -050046#import "utils.h"
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040047
Olivier Soldanod4311552017-11-20 15:09:53 -050048@interface SmartViewVC () <NSTableViewDelegate, NSTableViewDataSource, NSPopoverDelegate, ContextMenuDelegate, ContactLinkedDelegate, KeyboardShortcutDelegate> {
Alexandre Lision0f66bd32016-01-18 11:30:45 -050049
Alexandre Lision61db3552015-10-22 19:12:52 -040050 NSPopover* addToContactPopover;
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040051
52 //UI elements
Olivier Soldanod4311552017-11-20 15:09:53 -050053 __unsafe_unretained IBOutlet RingTableView* smartView;
Alexandre Lision61db3552015-10-22 19:12:52 -040054 __unsafe_unretained IBOutlet NSSearchField* searchField;
Alexandre Lision45c18672016-11-02 15:24:45 -040055
56 /* Pending ring usernames lookup for the search entry */
Olivier Soldanod4311552017-11-20 15:09:53 -050057 QMetaObject::Connection usernameLookupConnection, modelSortedConnection_, filterChangedConnection_;
58
59 lrc::api::ConversationModel* model_;
60 std::string selectedUid_;
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040061}
62
63@end
64
65@implementation SmartViewVC
66
Kateryna Kostiuk882cbac2017-07-05 17:29:00 -040067@synthesize tabbar;
68
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040069// Tags for views
Alexandre Lision57914fa2016-02-10 14:52:24 -050070NSInteger const IMAGE_TAG = 100;
71NSInteger const DISPLAYNAME_TAG = 200;
72NSInteger const DETAILS_TAG = 300;
73NSInteger const CALL_BUTTON_TAG = 400;
74NSInteger const TXT_BUTTON_TAG = 500;
75NSInteger const CANCEL_BUTTON_TAG = 600;
Kateryna Kostiuk6a536362017-05-02 14:26:12 -040076NSInteger const RING_ID_LABEL = 700;
Kateryna Kostiukd9039e92017-05-24 14:29:54 -040077NSInteger const PRESENCE_TAG = 800;
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040078
79- (void)awakeFromNib
80{
81 NSLog(@"INIT SmartView VC");
Olivier Soldanod4311552017-11-20 15:09:53 -050082 //get selected account
83 //encapsulate conversationmodel in local version
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040084
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040085 [smartView setTarget:self];
86 [smartView setDoubleAction:@selector(placeCall:)];
87
Alexandre Lision61db3552015-10-22 19:12:52 -040088 [smartView setContextMenuDelegate:self];
89 [smartView setShortcutsDelegate:self];
90
Olivier Soldanod4311552017-11-20 15:09:53 -050091 [smartView setDataSource: self];
Kateryna Kostiuk1f705ab2017-04-18 12:45:59 -040092
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040093 [self.view setWantsLayer:YES];
94 [self.view setLayer:[CALayer layer]];
95 [self.view.layer setBackgroundColor:[NSColor whiteColor].CGColor];
96
97 [searchField setWantsLayer:YES];
98 [searchField setLayer:[CALayer layer]];
99 [searchField.layer setBackgroundColor:[NSColor colorWithCalibratedRed:0.949 green:0.949 blue:0.949 alpha:0.9].CGColor];
100}
101
102- (void)placeCall:(id)sender
103{
Olivier Soldanod4311552017-11-20 15:09:53 -0500104 NSInteger row;
105 if (sender != nil && [sender clickedRow] != -1)
106 row = [sender clickedRow];
107 else if ([smartView selectedRow] != -1)
108 row = [smartView selectedRow];
109 else
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400110 return;
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400111
Olivier Soldanod4311552017-11-20 15:09:53 -0500112 auto conv = model_->filteredConversation(row);
113 model_->placeCall(conv.uid);
114}
115
116-(void) reloadData
117{
118 [smartView deselectAll:nil];
119 [smartView reloadData];
120
121 if (!selectedUid_.empty() && model_ != nil) {
122 auto it = std::find_if(model_->allFilteredConversations().begin(), model_->allFilteredConversations().end(),
123 [self] (const lrc::api::conversation::Info& conv) {
124 return selectedUid_ == conv.uid;
125 });
126 if (it != model_->allFilteredConversations().end()) {
127 NSIndexSet* indexSet = [NSIndexSet indexSetWithIndex:(it - model_->allFilteredConversations().begin())];
128 [smartView selectRowIndexes:indexSet byExtendingSelection:NO];
129 } else {
130 selectedUid_.clear();
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400131 }
132 }
133
Olivier Soldanod4311552017-11-20 15:09:53 -0500134 [smartView scrollToBeginningOfDocument:nil];
135}
136
137- (void)setConversationModel:(lrc::api::ConversationModel *)conversationModel
138{
139 if (model_ != conversationModel) {
140 model_ = conversationModel;
141 [self reloadData];
142 QObject::disconnect(modelSortedConnection_);
143 if (model_ != nil) {
144 modelSortedConnection_ = QObject::connect(model_, &lrc::api::ConversationModel::modelSorted,
145 [self] (){
146 [self reloadData];
147 });
148 filterChangedConnection_ = QObject::connect(model_, &lrc::api::ConversationModel::filterChanged,
149 [self] (){
150 [self reloadData];
151 });
152 }
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400153 }
154}
155
Olivier Soldanod4311552017-11-20 15:09:53 -0500156#pragma mark - NSTableViewDelegate methods
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400157
Olivier Soldanod4311552017-11-20 15:09:53 -0500158- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400159{
160 return YES;
161}
162
Olivier Soldanod4311552017-11-20 15:09:53 -0500163- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400164{
165 return NO;
166}
167
Olivier Soldanod4311552017-11-20 15:09:53 -0500168- (void)tableViewSelectionDidChange:(NSNotification *)notification
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400169{
Olivier Soldanod4311552017-11-20 15:09:53 -0500170 NSInteger row = [notification.object selectedRow];
171
172 if (row == -1)
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400173 return;
Olivier Soldanod4311552017-11-20 15:09:53 -0500174
175 auto uid = model_->filteredConversation(row).uid;
176 if (selectedUid_ != uid) {
177 selectedUid_ = uid;
178 model_->selectConversation(uid);
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400179 }
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400180}
181
Olivier Soldanod4311552017-11-20 15:09:53 -0500182- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400183{
Olivier Soldanod4311552017-11-20 15:09:53 -0500184 return [tableView makeViewWithIdentifier:@"HoverRowView" owner:nil];
185}
Alexandre Lisiona4bb0512016-04-19 18:04:31 -0400186
Olivier Soldanod4311552017-11-20 15:09:53 -0500187- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
188{
189 if (model_ == nil)
190 return nil;
191
192 auto conversation = model_->filteredConversation(row);
Alexandre Lisiona4bb0512016-04-19 18:04:31 -0400193 NSTableCellView* result;
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400194
Olivier Soldanod4311552017-11-20 15:09:53 -0500195 result = [tableView makeViewWithIdentifier:@"MainCell" owner:tableView];
196// NSTextField* details = [result viewWithTag:DETAILS_TAG];
Alexandre Lision4e280d62015-09-09 15:56:30 -0400197
Olivier Soldanod4311552017-11-20 15:09:53 -0500198 NSMutableArray* controls = [NSMutableArray arrayWithObject:[result viewWithTag:CALL_BUTTON_TAG]];
199 [((ContextualTableCellView*) result) setContextualsControls:controls];
200 [((ContextualTableCellView*) result) setShouldBlurParentView:YES];
Alexandre Lision21666f32015-09-22 17:04:36 -0400201
Olivier Soldanod4311552017-11-20 15:09:53 -0500202// if (auto call = RecentModel::instance().getActiveCall(qIdx)) {
203// [details setStringValue:call->roleData((int)Ring::Role::FormattedState).toString().toNSString()];
204// [((ContextualTableCellView*) result) setActiveState:YES];
205// } else {
206// [details setStringValue:qIdx.data((int)Ring::Role::FormattedLastUsed).toString().toNSString()];
207// [((ContextualTableCellView*) result) setActiveState:NO];
208// }
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500209
Olivier Soldanod4311552017-11-20 15:09:53 -0500210 NSTextField* unreadCount = [result viewWithTag:TXT_BUTTON_TAG];
211 [unreadCount setHidden:(conversation.unreadMessages == 0)];
212 [unreadCount setIntValue:conversation.unreadMessages];
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400213
214 NSTextField* displayName = [result viewWithTag:DISPLAYNAME_TAG];
Olivier Soldanod4311552017-11-20 15:09:53 -0500215 NSString* displayNameString = bestNameForConversation(conversation, *model_);
216 NSString* displayIDString = bestIDForConversation(conversation, *model_);
Kateryna Kostiuk6a536362017-05-02 14:26:12 -0400217 if(displayNameString.length == 0 || [displayNameString isEqualToString:displayIDString]) {
Anthony LĂ©onard4adc3f02017-07-21 10:23:04 -0400218 NSTextField* displayRingID = [result viewWithTag:RING_ID_LABEL];
Kateryna Kostiuk6a536362017-05-02 14:26:12 -0400219 [displayName setStringValue:displayIDString];
Anthony LĂ©onard4adc3f02017-07-21 10:23:04 -0400220 [displayRingID setHidden:YES];
Kateryna Kostiuk9d6657a2017-04-25 13:42:25 -0400221 }
Kateryna Kostiuk6a536362017-05-02 14:26:12 -0400222 else {
223 NSTextField* displayRingID = [result viewWithTag:RING_ID_LABEL];
224 [displayName setStringValue:displayNameString];
Kateryna Kostiuk6a536362017-05-02 14:26:12 -0400225 [displayRingID setStringValue:displayIDString];
Anthony LĂ©onard4adc3f02017-07-21 10:23:04 -0400226 [displayRingID setHidden:NO];
Kateryna Kostiuk6a536362017-05-02 14:26:12 -0400227 }
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400228 NSImageView* photoView = [result viewWithTag:IMAGE_TAG];
Alexandre Lision43e91bc2016-04-19 18:04:52 -0400229
Olivier Soldanod4311552017-11-20 15:09:53 -0500230 auto& imageManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
231 [photoView setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(imageManip.conversationPhoto(conversation, model_->owner)))];
Kateryna Kostiukd9039e92017-05-24 14:29:54 -0400232
233 NSView* presenceView = [result viewWithTag:PRESENCE_TAG];
Olivier Soldanod4311552017-11-20 15:09:53 -0500234 if (model_->owner.contactModel->getContact(conversation.participants[0]).isPresent) {
Kateryna Kostiukd9039e92017-05-24 14:29:54 -0400235 [presenceView setHidden:NO];
236 } else {
237 [presenceView setHidden:YES];
238 }
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400239 return result;
240}
241
Olivier Soldanod4311552017-11-20 15:09:53 -0500242- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500243{
Olivier Soldanod4311552017-11-20 15:09:53 -0500244 return 60.0;
245}
246
247#pragma mark - NSTableDataSource methods
248
249- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
250{
251 if (tableView == smartView) {
252 if (model_ != nullptr)
253 return model_->allFilteredConversations().size();
254 }
255
256 return 0;
Alexandre Lision0f66bd32016-01-18 11:30:45 -0500257}
258
Kateryna Kostiuk882cbac2017-07-05 17:29:00 -0400259- (void)startCallForRow:(id)sender {
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400260 NSInteger row = [smartView rowForView:sender];
261 [smartView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
262 [self placeCall:nil];
263}
264
265- (IBAction)hangUpClickedAtRow:(id)sender {
266 NSInteger row = [smartView rowForView:sender];
Alexandre Lision57914fa2016-02-10 14:52:24 -0500267
Olivier Soldanod4311552017-11-20 15:09:53 -0500268 if (row == -1)
Alexandre Lisionac4f5b62016-02-17 13:53:12 -0500269 return;
Alexandre Lision45c18672016-11-02 15:24:45 -0400270
Olivier Soldanod4311552017-11-20 15:09:53 -0500271 auto conv = model_->filteredConversation(row);
272 auto& callId = conv.callId;
Alexandre Lisionac4f5b62016-02-17 13:53:12 -0500273
Olivier Soldanod4311552017-11-20 15:09:53 -0500274 if (callId.empty())
275 return;
276
277 auto* callModel = model_->owner.callModel.get();
278 callModel->hangUp(callId);
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400279}
280
Alexandre Lision45c18672016-11-02 15:24:45 -0400281- (void) displayErrorModalWithTitle:(NSString*) title WithMessage:(NSString*) message
282{
283 NSAlert* alert = [NSAlert alertWithMessageText:title
284 defaultButton:@"Ok"
285 alternateButton:nil
286 otherButton:nil
287 informativeTextWithFormat:message];
288
289 [alert beginSheetModalForWindow:self.view.window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
290}
291
Olivier Soldanod4311552017-11-20 15:09:53 -0500292- (void) processSearchFieldInput
Alexandre Lision45c18672016-11-02 15:24:45 -0400293{
Olivier Soldanod4311552017-11-20 15:09:53 -0500294 model_->setFilter(std::string([[searchField stringValue] UTF8String]));
Alexandre Lision45c18672016-11-02 15:24:45 -0400295}
296
Olivier Soldanod4311552017-11-20 15:09:53 -0500297-(const lrc::api::account::Info&) chosenAccount
Kateryna Kostiukd2f7b5d2017-06-09 15:30:49 -0400298{
Olivier Soldanod4311552017-11-20 15:09:53 -0500299 return model_->owner;
Kateryna Kostiukd2f7b5d2017-06-09 15:30:49 -0400300}
301
Alexandre Lisionf909fb12016-11-03 12:35:36 -0400302- (void) clearSearchField
303{
304 [searchField setStringValue:@""];
Olivier Soldanod4311552017-11-20 15:09:53 -0500305 [self processSearchFieldInput];
Kateryna Kostiuk9dd759c2017-07-11 12:06:55 -0400306}
307
Alexandre Lision72a669e2016-09-14 17:52:16 -0400308/**
309 Copy a NSString in the general Pasteboard
310
311 @param sender the NSObject containing the represented object to copy
312 */
313- (void) copyStringToPasteboard:(id) sender
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400314{
315 NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
316 [pasteBoard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
317 [pasteBoard setString:[sender representedObject] forType:NSStringPboardType];
318}
319
Alexandre Lisionbf0385e2015-10-22 17:36:28 -0400320#pragma NSTextFieldDelegate
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400321
322- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector
323{
324 if (commandSelector == @selector(insertNewline:)) {
325 if([[searchField stringValue] isNotEqualTo:@""]) {
Olivier Soldanod4311552017-11-20 15:09:53 -0500326 [self processSearchFieldInput];
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400327 return YES;
328 }
329 }
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400330 return NO;
331}
332
Alexandre Lisionac4f5b62016-02-17 13:53:12 -0500333- (void)controlTextDidChange:(NSNotification *) notification
334{
Olivier Soldanod4311552017-11-20 15:09:53 -0500335 [self processSearchFieldInput];
Alexandre Lisionac4f5b62016-02-17 13:53:12 -0500336}
337
Alexandre Lision61db3552015-10-22 19:12:52 -0400338#pragma mark - NSPopOverDelegate
339
340- (void)popoverDidClose:(NSNotification *)notification
341{
342 if (addToContactPopover != nullptr) {
343 [addToContactPopover performClose:self];
344 addToContactPopover = NULL;
345 }
346}
347
Alexandre Lisionbf0385e2015-10-22 17:36:28 -0400348
Alexandre Lision61db3552015-10-22 19:12:52 -0400349#pragma mark - ContactLinkedDelegate
350
351- (void)contactLinked
352{
353 if (addToContactPopover != nullptr) {
354 [addToContactPopover performClose:self];
355 addToContactPopover = NULL;
356 }
357}
358
359#pragma mark - KeyboardShortcutDelegate
360
361- (void) onAddShortcut
362{
Olivier Soldanod4311552017-11-20 15:09:53 -0500363 if ([smartView selectedRow] == -1)
Alexandre Lision61db3552015-10-22 19:12:52 -0400364 return;
365
Olivier Soldanod4311552017-11-20 15:09:53 -0500366 auto uid = model_->filteredConversation([smartView selectedRow]).uid;
367 model_->makePermanent(uid);
Alexandre Lision61db3552015-10-22 19:12:52 -0400368}
369
370#pragma mark - ContextMenuDelegate
371
Olivier Soldanod4311552017-11-20 15:09:53 -0500372#if 0
373// TODO: Reimplement contextual menu with new models and behaviors
Alexandre Lision12946a72016-03-08 13:39:34 -0500374- (NSMenu*) contextualMenuForIndex:(NSTreeNode*) item
Alexandre Lision61db3552015-10-22 19:12:52 -0400375{
Alexandre Lision12946a72016-03-08 13:39:34 -0500376 auto qIdx = [treeController toQIdx:item];
377
378 if (!qIdx.isValid()) {
379 return nil;
380 }
381
Alexandre Lision61db3552015-10-22 19:12:52 -0400382 auto originIdx = RecentModel::instance().peopleProxy()->mapToSource(qIdx);
383 auto contactmethods = RecentModel::instance().getContactMethods(originIdx);
384 if (contactmethods.isEmpty())
385 return nil;
386
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400387 NSMenu *theMenu = [[NSMenu alloc] initWithTitle:@""];
388
389 if (contactmethods.size() == 1
390 && !contactmethods.first()->contact()
391 || contactmethods.first()->contact()->isPlaceHolder()) {
392
Kateryna Kostiuk9dd759c2017-07-11 12:06:55 -0400393 NSMenuItem* addContactItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Add to contacts", @"Contextual menu action")
394 action:@selector(addContactForRow:)
395 keyEquivalent:@""];
396 [addContactItem setRepresentedObject:item];
397 [theMenu addItem:addContactItem];
Alexandre Lision72a669e2016-09-14 17:52:16 -0400398 } else if (auto person = contactmethods.first()->contact()) {
399 NSMenuItem* copyNameItem = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Copy name", @"Contextual menu action")
400 action:@selector(copyStringToPasteboard:)
401 keyEquivalent:@""];
402
403 [copyNameItem setRepresentedObject:person->formattedName().toNSString()];
404 [theMenu addItem:copyNameItem];
Alexandre Lision61db3552015-10-22 19:12:52 -0400405 }
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400406
407 NSMenu* copySubmenu = [[NSMenu alloc] init];
408 NSMenu* callSubmenu = [[NSMenu alloc] init];
409
Alexandre Lision72a669e2016-09-14 17:52:16 -0400410 for (auto cm : contactmethods) {
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400411 NSMenuItem* tmpCopyItem = [[NSMenuItem alloc] initWithTitle:cm->uri().toNSString()
Alexandre Lision72a669e2016-09-14 17:52:16 -0400412 action:@selector(copyStringToPasteboard:)
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400413 keyEquivalent:@""];
414
415 [tmpCopyItem setRepresentedObject:cm->uri().toNSString()];
416 [copySubmenu addItem:tmpCopyItem];
417
418 NSMenuItem* tmpCallItem = [[NSMenuItem alloc] initWithTitle:cm->uri().toNSString()
419 action:@selector(callNumber:)
420 keyEquivalent:@""];
421 [tmpCallItem setRepresentedObject:cm->uri().toNSString()];
422 [callSubmenu addItem:tmpCallItem];
423 }
424
Alexandre Lision72a669e2016-09-14 17:52:16 -0400425 NSMenuItem* copyNumberItem = [[NSMenuItem alloc] init];
426 [copyNumberItem setTitle:NSLocalizedString(@"Copy number", @"Contextual menu action")];
427 [copyNumberItem setSubmenu:copySubmenu];
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400428
429 NSMenuItem* callItems = [[NSMenuItem alloc] init];
430 [callItems setTitle:NSLocalizedString(@"Call number", @"Contextual menu action")];
431 [callItems setSubmenu:callSubmenu];
432
Alexandre Lision72a669e2016-09-14 17:52:16 -0400433 [theMenu insertItem:copyNumberItem atIndex:theMenu.itemArray.count];
Alexandre Lisiond7bf2882015-10-22 22:54:32 -0400434 [theMenu insertItem:[NSMenuItem separatorItem] atIndex:theMenu.itemArray.count];
435 [theMenu insertItem:callItems atIndex:theMenu.itemArray.count];
436
437 return theMenu;
Alexandre Lision61db3552015-10-22 19:12:52 -0400438}
Olivier Soldanod4311552017-11-20 15:09:53 -0500439#endif
Alexandre Lision61db3552015-10-22 19:12:52 -0400440
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400441@end