blob: 53de98b84851995a29637da5cc7ca0912f46e13f [file] [log] [blame]
Alexandre Lisionf5fc4792015-03-17 09:15:43 -04001/*
Alexandre Lision9fe374b2016-01-06 10:17:31 -05002 * Copyright (C) 2015-2016 Savoir-faire Linux Inc.
Alexandre Lisionf5fc4792015-03-17 09:15:43 -04003 * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040018 */
19#import "AccSecurityVC.h"
20
Alexandre Lision4de68ce2015-04-24 18:22:49 -040021#import <QUrl>
22#import <certificate.h>
23#import <tlsmethodmodel.h>
24#import <qitemselectionmodel.h>
25#import <ciphermodel.h>
Alexandre Lision7f3164c2015-06-12 11:45:37 -040026#import <accountmodel.h>
Alexandre Lision4de68ce2015-04-24 18:22:49 -040027
28#import "QNSTreeController.h"
29#import "CertificateWC.h"
30
Alexandre Lision4de68ce2015-04-24 18:22:49 -040031#define COLUMNID_NAME @"CipherNameColumn"
32#define COLUMNID_STATE @"CipherStateColumn"
33
Alexandre Lision24805d52015-08-12 14:29:11 -040034@interface AccSecurityVC () {
35 __unsafe_unretained IBOutlet NSOutlineView *cipherListView;
36 __unsafe_unretained IBOutlet NSButton *useTLS;
37 __unsafe_unretained IBOutlet NSView *tlsContainer;
38
39 __unsafe_unretained IBOutlet NSView *pvkContainer;
40 __unsafe_unretained IBOutlet NSImageView *pvkPasswordValidation;
41
42 __unsafe_unretained IBOutlet NSButton *showUserCertButton;
43 __unsafe_unretained IBOutlet NSButton *showCAButton;
44 __unsafe_unretained IBOutlet NSSecureTextField *pvkPasswordField;
45 __unsafe_unretained IBOutlet NSTextField *outgoingTlsServerName;
46 __unsafe_unretained IBOutlet NSTextField *tlsNegotiationTimeout;
47 __unsafe_unretained IBOutlet NSStepper *tlsNegotiationTimeoutStepper;
48 __unsafe_unretained IBOutlet NSPathControl *caListPathControl;
49 __unsafe_unretained IBOutlet NSPathControl *certificatePathControl;
50 __unsafe_unretained IBOutlet NSPathControl *pvkPathControl;
51 __unsafe_unretained IBOutlet NSPopUpButton *tlsMethodList;
52 __unsafe_unretained IBOutlet NSButton *srtpRTPFallback;
53 __unsafe_unretained IBOutlet NSButton *useSRTP;
54
55 __unsafe_unretained IBOutlet NSButton *verifyCertAsClientButton;
56 __unsafe_unretained IBOutlet NSButton *verifyCertAsServerButton;
57 __unsafe_unretained IBOutlet NSButton *requireCertButton;
58}
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040059
Alexandre Lision81c97212015-06-17 15:51:53 -040060@property QNSTreeController *treeController;
Alexandre Lision4de68ce2015-04-24 18:22:49 -040061@property CertificateWC* certificateWC;
62
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040063@end
64
65@implementation AccSecurityVC
Alexandre Lision4de68ce2015-04-24 18:22:49 -040066@synthesize treeController;
Alexandre Lision4de68ce2015-04-24 18:22:49 -040067@synthesize certificateWC;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040068
Alexandre Lision51ff1492016-04-15 11:38:37 -040069// Tags for views
70NS_ENUM(NSInteger, TagViews) {
71 PVK_PASSWORD = 0,
72 OUTGOING_TLS_SRV_NAME = 1,
73 TLS_NEGOTIATION = 2
74};
75
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040076- (void)awakeFromNib
77{
78 NSLog(@"INIT Security VC");
Alexandre Lision51ff1492016-04-15 11:38:37 -040079 [pvkPasswordField setTag:TagViews::PVK_PASSWORD];
80 [outgoingTlsServerName setTag:TagViews::OUTGOING_TLS_SRV_NAME];
81 [tlsNegotiationTimeoutStepper setTag:TagViews::TLS_NEGOTIATION];
82 [tlsNegotiationTimeout setTag:TagViews::TLS_NEGOTIATION];
Alexandre Lision4de68ce2015-04-24 18:22:49 -040083
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -040084 QObject::connect(AccountModel::instance().selectionModel(),
Alexandre Lision7f3164c2015-06-12 11:45:37 -040085 &QItemSelectionModel::currentChanged,
86 [=](const QModelIndex &current, const QModelIndex &previous) {
87 if(!current.isValid())
88 return;
89 [self loadAccount];
90 });
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040091}
92
Alexandre Lision7f3164c2015-06-12 11:45:37 -040093- (Account*) currentAccount
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040094{
Alexandre Lisiond3aa3ad2015-10-23 14:28:41 -040095 auto accIdx = AccountModel::instance().selectionModel()->currentIndex();
96 return AccountModel::instance().getAccountByModelIndex(accIdx);
Alexandre Lision7f3164c2015-06-12 11:45:37 -040097}
98
99- (void)loadAccount
100{
101 auto account = [self currentAccount];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400102
Alexandre Lision51ff1492016-04-15 11:38:37 -0400103 [self updateControlsWithTag:TagViews::PVK_PASSWORD];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400104 [self updateControlsWithTag:OUTGOING_TLS_SRV_NAME];
Alexandre Lision51ff1492016-04-15 11:38:37 -0400105 [self updateControlsWithTag:TagViews::TLS_NEGOTIATION];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400106
Alexandre Lision81c97212015-06-17 15:51:53 -0400107 QModelIndex qTlsMethodIdx = account->tlsMethodModel()->selectionModel()->currentIndex();
Alexandre Lision24805d52015-08-12 14:29:11 -0400108 [tlsMethodList removeAllItems];
109 [tlsMethodList addItemWithTitle:qTlsMethodIdx.data(Qt::DisplayRole).toString().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400110
Alexandre Lision81c97212015-06-17 15:51:53 -0400111 treeController = [[QNSTreeController alloc] initWithQModel:account->cipherModel()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400112 [treeController setAvoidsEmptySelection:NO];
113 [treeController setAlwaysUsesMultipleValuesMarker:YES];
114 [treeController setChildrenKeyPath:@"children"];
115
116 [cipherListView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
117 [cipherListView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil];
118 [cipherListView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
119
Alexandre Lision24805d52015-08-12 14:29:11 -0400120 [useTLS setState:account->isTlsEnabled()];
121 [tlsContainer setHidden:!account->isTlsEnabled()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400122
Alexandre Lision24805d52015-08-12 14:29:11 -0400123 [useSRTP setState:account->isSrtpEnabled()];
124 [srtpRTPFallback setState:account->isSrtpRtpFallback()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400125 [srtpRTPFallback setEnabled:useSRTP.state];
126
Alexandre Lision24805d52015-08-12 14:29:11 -0400127 if(account->tlsCaListCertificate() != nil) {
128 [caListPathControl setURL:[NSURL fileURLWithPath:account->tlsCaListCertificate()->path().toNSString()]];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400129 } else {
130 [caListPathControl setURL:nil];
131 }
132
Alexandre Lision24805d52015-08-12 14:29:11 -0400133 auto tlsCert = account->tlsCertificate();
134
135 if(tlsCert != nil) {
136 [certificatePathControl setURL:[NSURL fileURLWithPath:tlsCert->path().toNSString()]];
137 if(tlsCert->requirePrivateKey()) {
138 [pvkContainer setHidden:NO];
139 if(!account->tlsPrivateKey().isEmpty()) {
140 [pvkPathControl setURL:[NSURL fileURLWithPath:account->tlsPrivateKey().toNSString()]];
141 if (tlsCert->requirePrivateKeyPassword()) {
142 [pvkPasswordField setHidden:NO];
143 } else
144 [pvkPasswordField setHidden:YES];
145 } else {
146 [pvkPathControl setURL:nil];
147 }
148 } else {
149 [pvkContainer setHidden:YES];
150 }
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400151 } else {
152 [certificatePathControl setURL:nil];
153 }
154
Alexandre Lision24805d52015-08-12 14:29:11 -0400155 if (account->tlsCaListCertificate())
156 [showCAButton setHidden:!(account->tlsCaListCertificate()->isValid() == Certificate::CheckValues::PASSED)];
157 else
158 [showCAButton setHidden:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400159
Alexandre Lision24805d52015-08-12 14:29:11 -0400160 [verifyCertAsServerButton setState:account->isTlsVerifyServer()];
161 [verifyCertAsClientButton setState:account->isTlsVerifyClient()];
162 [requireCertButton setState:account->isTlsRequireClientCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400163}
164
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400165- (IBAction)chooseTlsMethod:(id)sender {
166 int index = [sender indexOfSelectedItem];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400167 QModelIndex qIdx = [self currentAccount]->tlsMethodModel()->index(index, 0);
168 [self currentAccount]->tlsMethodModel()->selectionModel()->setCurrentIndex(qIdx, QItemSelectionModel::ClearAndSelect);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400169}
170
171- (IBAction)toggleUseTLS:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400172 [self currentAccount]->setTlsEnabled([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400173 [tlsContainer setHidden:![sender state]];
174}
175
176- (IBAction)toggleUseSRTP:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400177 [self currentAccount]->setSrtpEnabled([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400178 [srtpRTPFallback setEnabled:[sender state]];
179}
180- (IBAction)toggleRTPFallback:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400181 [self currentAccount]->setSrtpRtpFallback([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400182}
183
184- (IBAction)toggleVerifyCertAsClient:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400185 [self currentAccount]->setTlsVerifyClient([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400186}
187
188- (IBAction)toggleVerifyCertServer:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400189 [self currentAccount]->setTlsVerifyServer([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400190}
191
192- (IBAction)toggleRequireCert:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400193 [self currentAccount]->setTlsRequireClientCertificate([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400194}
195
196- (IBAction)toggleCipher:(id)sender {
197 NSInteger row = [sender clickedRow];
198 NSTableColumn *col = [sender tableColumnWithIdentifier:COLUMNID_STATE];
199 NSButtonCell *cell = [col dataCellForRow:row];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400200 [self currentAccount]->cipherModel()->setData([self currentAccount]->cipherModel()->index(row, 0, QModelIndex()),
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400201 cell.state == NSOnState ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
202}
203
204- (void) updateControlsWithTag:(NSInteger) tag
205{
206 switch (tag) {
Alexandre Lision51ff1492016-04-15 11:38:37 -0400207 case TagViews::PVK_PASSWORD: {
Alexandre Lision24805d52015-08-12 14:29:11 -0400208 [pvkPasswordField setStringValue:[self currentAccount]->tlsPassword().toNSString()];
209 BOOL passMatch = [self currentAccount]->tlsCertificate() &&
210 [self currentAccount]->tlsCertificate()->privateKeyMatch() == Certificate::CheckValues::PASSED;
211 [pvkPasswordValidation setImage:[NSImage imageNamed:passMatch?@"ic_action_accept":@"ic_action_cancel"]];
212 }
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400213 break;
Alexandre Lision51ff1492016-04-15 11:38:37 -0400214 case TagViews::OUTGOING_TLS_SRV_NAME:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400215 [outgoingTlsServerName setStringValue:[self currentAccount]->tlsServerName().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400216 break;
Alexandre Lision51ff1492016-04-15 11:38:37 -0400217 case TagViews::TLS_NEGOTIATION:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400218 [tlsNegotiationTimeout setIntegerValue:[self currentAccount]->tlsNegotiationTimeoutSec()];
219 [tlsNegotiationTimeoutStepper setIntegerValue:[self currentAccount]->tlsNegotiationTimeoutSec()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400220 break;
221 default:
222 break;
223 }
224}
225
226#pragma mark - NSTextFieldDelegate methods
227
228-(void)controlTextDidChange:(NSNotification *)notif
229{
230 NSTextField *textField = [notif object];
231 NSRange test = [[textField currentEditor] selectedRange];
232
233 [self valueDidChange:textField];
234 //FIXME: saving account lose focus because in NSTreeController we remove and reinsert row so View selction change
235 [textField.window makeFirstResponder:textField];
236 [[textField currentEditor] setSelectedRange:test];
237}
238
239- (IBAction) valueDidChange: (id) sender
240{
241 switch ([sender tag]) {
Alexandre Lision51ff1492016-04-15 11:38:37 -0400242 case TagViews::PVK_PASSWORD:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400243 [self currentAccount]->setTlsPassword([[sender stringValue] UTF8String]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400244 break;
Alexandre Lision51ff1492016-04-15 11:38:37 -0400245 case TagViews::OUTGOING_TLS_SRV_NAME:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400246 [self currentAccount]->setTlsServerName([[sender stringValue] UTF8String]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400247 break;
Alexandre Lision51ff1492016-04-15 11:38:37 -0400248 case TagViews::TLS_NEGOTIATION:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400249 [self currentAccount]->setTlsNegotiationTimeoutSec([sender integerValue]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400250 break;
251 default:
252 break;
253 }
254 [self updateControlsWithTag:[sender tag]];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400255}
256
257#pragma mark - NSPathControl delegate methods
Alexandre Lision24805d52015-08-12 14:29:11 -0400258
259- (IBAction)caListPathControlSingleClick:(id)sender
260{
261 NSURL* fileURL;
262 if ([sender isKindOfClass:[NSMenuItem class]]) {
263 fileURL = nil;
264 } else {
265 fileURL = [[sender clickedPathComponentCell] URL];
266 }
267 [self->caListPathControl setURL:fileURL];
268 [self currentAccount]->setTlsCaListCertificate([[fileURL path] UTF8String]);
269
270 if ([self currentAccount]->tlsCaListCertificate()->isValid() == Certificate::CheckValues::PASSED) {
271 [showCAButton setHidden:NO];
272 } else
273 [showCAButton setHidden:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400274}
275
Alexandre Lision24805d52015-08-12 14:29:11 -0400276- (IBAction)certificatePathControlSingleClick:(id)sender
277{
278 NSURL* fileURL;
279 if ([sender isKindOfClass:[NSMenuItem class]]) {
280 fileURL = nil;
281 } else {
282 fileURL = [[sender clickedPathComponentCell] URL];
283 }
284 [self->certificatePathControl setURL:fileURL];
285 [self currentAccount]->setTlsCertificate([[fileURL path] UTF8String]);
286
287 auto cert = [self currentAccount]->tlsCertificate();
288
289 if (cert) {
290 [showUserCertButton setHidden:!(cert->isValid() == Certificate::CheckValues::PASSED)];
291 [pvkContainer setHidden:!cert->requirePrivateKey()];
292 } else {
293 [showUserCertButton setHidden:YES];
294 [pvkContainer setHidden:YES];
295 }
296
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400297}
298
Alexandre Lision24805d52015-08-12 14:29:11 -0400299- (IBAction)pvkFilePathControlSingleClick:(id)sender
300{
301 NSURL* fileURL;
302 if ([sender isKindOfClass:[NSMenuItem class]]) {
303 fileURL = nil;
304 } else {
305 fileURL = [[sender clickedPathComponentCell] URL];
306 }
307 [self currentAccount]->setTlsPrivateKey([[fileURL path] UTF8String]);
308 if([self currentAccount]->tlsCertificate()->requirePrivateKeyPassword()) {
309 [pvkPasswordField setHidden:NO];
310 } else {
311 [pvkPasswordField setHidden:YES];
312 }
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400313}
314
315- (IBAction)showCA:(id)sender
316{
317 certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400318 [certificateWC setCertificate:[self currentAccount]->tlsCaListCertificate()];
Alexandre Lision4baba4c2016-02-11 13:00:57 -0500319#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_9
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400320 [self.view.window beginSheet:certificateWC.window completionHandler:nil];
Alexandre Lision4baba4c2016-02-11 13:00:57 -0500321#else
322 [NSApp beginSheet: certificateWC.window
323 modalForWindow: self.view.window
324 modalDelegate: self
325 didEndSelector: nil
326 contextInfo: nil];
327#endif
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400328}
329
330- (IBAction)showEndpointCertificate:(id)sender
331{
332 certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400333 [certificateWC setCertificate:[self currentAccount]->tlsCertificate()];
Alexandre Lision4baba4c2016-02-11 13:00:57 -0500334#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_9
335 [self.view.window beginSheet:certificateWC.window completionHandler:nil];
336#else
337 [NSApp beginSheet: certificateWC.window
338 modalForWindow: self.view.window
339 modalDelegate: self
340 didEndSelector: nil
341 contextInfo: nil];
342#endif
343}
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400344
Alexandre Lision51ff1492016-04-15 11:38:37 -0400345#pragma mark - NSPathControlDelegate methods
346
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400347- (void)pathControl:(NSPathControl *)pathControl willDisplayOpenPanel:(NSOpenPanel *)openPanel
348{
349 NSLog(@"willDisplayOpenPanel");
350 [openPanel setAllowsMultipleSelection:NO];
351 [openPanel setCanChooseDirectories:NO];
352 [openPanel setCanChooseFiles:YES];
353 [openPanel setResolvesAliases:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400354
Alexandre Lision24805d52015-08-12 14:29:11 -0400355 if(pathControl == caListPathControl) {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400356 [openPanel setTitle:NSLocalizedString(@"Choose a CA list", @"Open panel title")];
Alexandre Lision24805d52015-08-12 14:29:11 -0400357 } else if (pathControl == certificatePathControl) {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400358 [openPanel setTitle:NSLocalizedString(@"Choose a certificate", @"Open panel title")];
359 } else {
360 [openPanel setTitle:NSLocalizedString(@"Choose a private key file", @"Open panel title")];
361 }
362
Alexandre Lision922380d2015-09-15 10:25:17 -0400363 [openPanel setPrompt:NSLocalizedString(@"Choose CA", @"Open panel prompt for 'Choose a file'")];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400364 [openPanel setDelegate:self];
365}
366
367- (void)pathControl:(NSPathControl *)pathControl willPopUpMenu:(NSMenu *)menu
368{
Alexandre Lision24805d52015-08-12 14:29:11 -0400369 NSMenuItem *item;
370 if(pathControl == caListPathControl) {
Alexandre Lision7f01b072015-09-15 14:57:05 -0400371 item = [menu addItemWithTitle:NSLocalizedString(@"Remove value", @"Contextual menu entry")
372 action:@selector(caListPathControlSingleClick:) keyEquivalent:@""];
Alexandre Lision24805d52015-08-12 14:29:11 -0400373 } else if (pathControl == certificatePathControl) {
Alexandre Lision7f01b072015-09-15 14:57:05 -0400374 item = [menu addItemWithTitle:NSLocalizedString(@"Remove value", @"Contextual menu entry")
375 action:@selector(certificatePathControlSingleClick:) keyEquivalent:@""];
Alexandre Lision24805d52015-08-12 14:29:11 -0400376 } else {
Alexandre Lision7f01b072015-09-15 14:57:05 -0400377 item = [menu addItemWithTitle:NSLocalizedString(@"Remove value", @"Contextual menu entry")
378 action:@selector(pvkFilePathControlSingleClick:) keyEquivalent:@""];
Alexandre Lision24805d52015-08-12 14:29:11 -0400379 }
380 [item setTarget:self]; // or whatever target you want
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400381}
382
383#pragma mark - NSOpenSavePanelDelegate delegate methods
384
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400385- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
386{
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400387 return YES;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400388}
389
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400390#pragma mark - NSMenuDelegate methods
391
392- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400393{
Alexandre Lision51ff1492016-04-15 11:38:37 -0400394 auto qIdx = [self currentAccount]->tlsMethodModel()->index(index);
395 [item setTitle:qIdx.data(Qt::DisplayRole).toString().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400396 return YES;
397}
398
399- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
400{
Alexandre Lision51ff1492016-04-15 11:38:37 -0400401 return [self currentAccount]->tlsMethodModel()->rowCount();
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400402}
403
404#pragma mark - NSOutlineViewDelegate methods
405
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400406- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
407{
408 return YES;
409}
410
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400411- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item
412{
413 NSCell *returnCell = [tableColumn dataCell];
414 return returnCell;
415}
416
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400417- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
418{
Alexandre Lision51ff1492016-04-15 11:38:37 -0400419 if ([[fieldEditor string] length] == 0) {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400420 // don't allow empty node names
421 return NO;
Alexandre Lision51ff1492016-04-15 11:38:37 -0400422 } else {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400423 return YES;
424 }
425}
426
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400427- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
428{
429 return NO;
430}
431
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400432- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
433{
434 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
435 if(!qIdx.isValid())
436 return;
437
Alexandre Lision51ff1492016-04-15 11:38:37 -0400438 if ([[tableColumn identifier] isEqualToString:COLUMNID_NAME]) {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400439 cell.title = qIdx.data(Qt::DisplayRole).toString().toNSString();
440 }
441}
442
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400443@end