blob: ef955c8643a62266525939b6680570989a9ab400 [file] [log] [blame]
Alexandre Lisionf5fc4792015-03-17 09:15:43 -04001/*
2 * Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
3 * 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.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30#import "AccSecurityVC.h"
31
Alexandre Lision4de68ce2015-04-24 18:22:49 -040032#import <QUrl>
33#import <certificate.h>
34#import <tlsmethodmodel.h>
35#import <qitemselectionmodel.h>
36#import <ciphermodel.h>
Alexandre Lision7f3164c2015-06-12 11:45:37 -040037#import <accountmodel.h>
Alexandre Lision4de68ce2015-04-24 18:22:49 -040038
39#import "QNSTreeController.h"
40#import "CertificateWC.h"
41
42// Tags for views
43#define PVK_PASSWORD_TAG 0
44#define OUTGOING_TLS_SRV_NAME 1
45#define TLS_NEGOTIATION_TAG 2
46
47#define COLUMNID_NAME @"CipherNameColumn"
48#define COLUMNID_STATE @"CipherStateColumn"
49
Alexandre Lision24805d52015-08-12 14:29:11 -040050@interface AccSecurityVC () {
51 __unsafe_unretained IBOutlet NSOutlineView *cipherListView;
52 __unsafe_unretained IBOutlet NSButton *useTLS;
53 __unsafe_unretained IBOutlet NSView *tlsContainer;
54
55 __unsafe_unretained IBOutlet NSView *pvkContainer;
56 __unsafe_unretained IBOutlet NSImageView *pvkPasswordValidation;
57
58 __unsafe_unretained IBOutlet NSButton *showUserCertButton;
59 __unsafe_unretained IBOutlet NSButton *showCAButton;
60 __unsafe_unretained IBOutlet NSSecureTextField *pvkPasswordField;
61 __unsafe_unretained IBOutlet NSTextField *outgoingTlsServerName;
62 __unsafe_unretained IBOutlet NSTextField *tlsNegotiationTimeout;
63 __unsafe_unretained IBOutlet NSStepper *tlsNegotiationTimeoutStepper;
64 __unsafe_unretained IBOutlet NSPathControl *caListPathControl;
65 __unsafe_unretained IBOutlet NSPathControl *certificatePathControl;
66 __unsafe_unretained IBOutlet NSPathControl *pvkPathControl;
67 __unsafe_unretained IBOutlet NSPopUpButton *tlsMethodList;
68 __unsafe_unretained IBOutlet NSButton *srtpRTPFallback;
69 __unsafe_unretained IBOutlet NSButton *useSRTP;
70
71 __unsafe_unretained IBOutlet NSButton *verifyCertAsClientButton;
72 __unsafe_unretained IBOutlet NSButton *verifyCertAsServerButton;
73 __unsafe_unretained IBOutlet NSButton *requireCertButton;
74}
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040075
Alexandre Lision81c97212015-06-17 15:51:53 -040076@property QNSTreeController *treeController;
Alexandre Lision4de68ce2015-04-24 18:22:49 -040077@property CertificateWC* certificateWC;
78
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040079@end
80
81@implementation AccSecurityVC
Alexandre Lision4de68ce2015-04-24 18:22:49 -040082@synthesize treeController;
Alexandre Lision4de68ce2015-04-24 18:22:49 -040083@synthesize certificateWC;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040084
85- (void)awakeFromNib
86{
87 NSLog(@"INIT Security VC");
Alexandre Lision4de68ce2015-04-24 18:22:49 -040088 [pvkPasswordField setTag:PVK_PASSWORD_TAG];
89 [outgoingTlsServerName setTag:OUTGOING_TLS_SRV_NAME];
90 [tlsNegotiationTimeoutStepper setTag:TLS_NEGOTIATION_TAG];
91 [tlsNegotiationTimeout setTag:TLS_NEGOTIATION_TAG];
92
Alexandre Lision7f3164c2015-06-12 11:45:37 -040093 QObject::connect(AccountModel::instance()->selectionModel(),
94 &QItemSelectionModel::currentChanged,
95 [=](const QModelIndex &current, const QModelIndex &previous) {
96 if(!current.isValid())
97 return;
98 [self loadAccount];
99 });
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400100}
101
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400102- (Account*) currentAccount
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400103{
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400104 auto accIdx = AccountModel::instance()->selectionModel()->currentIndex();
105 return AccountModel::instance()->getAccountByModelIndex(accIdx);
106}
107
108- (void)loadAccount
109{
110 auto account = [self currentAccount];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400111
112 [self updateControlsWithTag:PVK_PASSWORD_TAG];
113 [self updateControlsWithTag:OUTGOING_TLS_SRV_NAME];
114 [self updateControlsWithTag:TLS_NEGOTIATION_TAG];
115
Alexandre Lision81c97212015-06-17 15:51:53 -0400116 QModelIndex qTlsMethodIdx = account->tlsMethodModel()->selectionModel()->currentIndex();
Alexandre Lision24805d52015-08-12 14:29:11 -0400117 [tlsMethodList removeAllItems];
118 [tlsMethodList addItemWithTitle:qTlsMethodIdx.data(Qt::DisplayRole).toString().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400119
Alexandre Lision81c97212015-06-17 15:51:53 -0400120 treeController = [[QNSTreeController alloc] initWithQModel:account->cipherModel()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400121 [treeController setAvoidsEmptySelection:NO];
122 [treeController setAlwaysUsesMultipleValuesMarker:YES];
123 [treeController setChildrenKeyPath:@"children"];
124
125 [cipherListView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
126 [cipherListView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil];
127 [cipherListView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
128
Alexandre Lision24805d52015-08-12 14:29:11 -0400129 [useTLS setState:account->isTlsEnabled()];
130 [tlsContainer setHidden:!account->isTlsEnabled()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400131
Alexandre Lision24805d52015-08-12 14:29:11 -0400132 [useSRTP setState:account->isSrtpEnabled()];
133 [srtpRTPFallback setState:account->isSrtpRtpFallback()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400134 [srtpRTPFallback setEnabled:useSRTP.state];
135
Alexandre Lision24805d52015-08-12 14:29:11 -0400136 if(account->tlsCaListCertificate() != nil) {
137 [caListPathControl setURL:[NSURL fileURLWithPath:account->tlsCaListCertificate()->path().toNSString()]];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400138 } else {
139 [caListPathControl setURL:nil];
140 }
141
Alexandre Lision24805d52015-08-12 14:29:11 -0400142 auto tlsCert = account->tlsCertificate();
143
144 if(tlsCert != nil) {
145 [certificatePathControl setURL:[NSURL fileURLWithPath:tlsCert->path().toNSString()]];
146 if(tlsCert->requirePrivateKey()) {
147 [pvkContainer setHidden:NO];
148 if(!account->tlsPrivateKey().isEmpty()) {
149 [pvkPathControl setURL:[NSURL fileURLWithPath:account->tlsPrivateKey().toNSString()]];
150 if (tlsCert->requirePrivateKeyPassword()) {
151 [pvkPasswordField setHidden:NO];
152 } else
153 [pvkPasswordField setHidden:YES];
154 } else {
155 [pvkPathControl setURL:nil];
156 }
157 } else {
158 [pvkContainer setHidden:YES];
159 }
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400160 } else {
161 [certificatePathControl setURL:nil];
162 }
163
Alexandre Lision24805d52015-08-12 14:29:11 -0400164 if (account->tlsCaListCertificate())
165 [showCAButton setHidden:!(account->tlsCaListCertificate()->isValid() == Certificate::CheckValues::PASSED)];
166 else
167 [showCAButton setHidden:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400168
Alexandre Lision24805d52015-08-12 14:29:11 -0400169 [verifyCertAsServerButton setState:account->isTlsVerifyServer()];
170 [verifyCertAsClientButton setState:account->isTlsVerifyClient()];
171 [requireCertButton setState:account->isTlsRequireClientCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400172}
173
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400174- (IBAction)chooseTlsMethod:(id)sender {
175 int index = [sender indexOfSelectedItem];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400176 QModelIndex qIdx = [self currentAccount]->tlsMethodModel()->index(index, 0);
177 [self currentAccount]->tlsMethodModel()->selectionModel()->setCurrentIndex(qIdx, QItemSelectionModel::ClearAndSelect);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400178}
179
180- (IBAction)toggleUseTLS:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400181 [self currentAccount]->setTlsEnabled([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400182 [tlsContainer setHidden:![sender state]];
183}
184
185- (IBAction)toggleUseSRTP:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400186 [self currentAccount]->setSrtpEnabled([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400187 [srtpRTPFallback setEnabled:[sender state]];
188}
189- (IBAction)toggleRTPFallback:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400190 [self currentAccount]->setSrtpRtpFallback([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400191}
192
193- (IBAction)toggleVerifyCertAsClient:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400194 [self currentAccount]->setTlsVerifyClient([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400195}
196
197- (IBAction)toggleVerifyCertServer:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400198 [self currentAccount]->setTlsVerifyServer([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400199}
200
201- (IBAction)toggleRequireCert:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400202 [self currentAccount]->setTlsRequireClientCertificate([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400203}
204
205- (IBAction)toggleCipher:(id)sender {
206 NSInteger row = [sender clickedRow];
207 NSTableColumn *col = [sender tableColumnWithIdentifier:COLUMNID_STATE];
208 NSButtonCell *cell = [col dataCellForRow:row];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400209 [self currentAccount]->cipherModel()->setData([self currentAccount]->cipherModel()->index(row, 0, QModelIndex()),
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400210 cell.state == NSOnState ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
211}
212
213- (void) updateControlsWithTag:(NSInteger) tag
214{
215 switch (tag) {
Alexandre Lision24805d52015-08-12 14:29:11 -0400216 case PVK_PASSWORD_TAG: {
217 [pvkPasswordField setStringValue:[self currentAccount]->tlsPassword().toNSString()];
218 BOOL passMatch = [self currentAccount]->tlsCertificate() &&
219 [self currentAccount]->tlsCertificate()->privateKeyMatch() == Certificate::CheckValues::PASSED;
220 [pvkPasswordValidation setImage:[NSImage imageNamed:passMatch?@"ic_action_accept":@"ic_action_cancel"]];
221 }
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400222 break;
223 case OUTGOING_TLS_SRV_NAME:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400224 [outgoingTlsServerName setStringValue:[self currentAccount]->tlsServerName().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400225 break;
226 case TLS_NEGOTIATION_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400227 [tlsNegotiationTimeout setIntegerValue:[self currentAccount]->tlsNegotiationTimeoutSec()];
228 [tlsNegotiationTimeoutStepper setIntegerValue:[self currentAccount]->tlsNegotiationTimeoutSec()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400229 break;
230 default:
231 break;
232 }
233}
234
235#pragma mark - NSTextFieldDelegate methods
236
237-(void)controlTextDidChange:(NSNotification *)notif
238{
239 NSTextField *textField = [notif object];
240 NSRange test = [[textField currentEditor] selectedRange];
241
242 [self valueDidChange:textField];
243 //FIXME: saving account lose focus because in NSTreeController we remove and reinsert row so View selction change
244 [textField.window makeFirstResponder:textField];
245 [[textField currentEditor] setSelectedRange:test];
246}
247
248- (IBAction) valueDidChange: (id) sender
249{
250 switch ([sender tag]) {
251 case PVK_PASSWORD_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400252 [self currentAccount]->setTlsPassword([[sender stringValue] UTF8String]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400253 break;
254 case OUTGOING_TLS_SRV_NAME:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400255 [self currentAccount]->setTlsServerName([[sender stringValue] UTF8String]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400256 break;
257 case TLS_NEGOTIATION_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400258 [self currentAccount]->setTlsNegotiationTimeoutSec([sender integerValue]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400259 break;
260 default:
261 break;
262 }
263 [self updateControlsWithTag:[sender tag]];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400264}
265
266#pragma mark - NSPathControl delegate methods
Alexandre Lision24805d52015-08-12 14:29:11 -0400267
268- (IBAction)caListPathControlSingleClick:(id)sender
269{
270 NSURL* fileURL;
271 if ([sender isKindOfClass:[NSMenuItem class]]) {
272 fileURL = nil;
273 } else {
274 fileURL = [[sender clickedPathComponentCell] URL];
275 }
276 [self->caListPathControl setURL:fileURL];
277 [self currentAccount]->setTlsCaListCertificate([[fileURL path] UTF8String]);
278
279 if ([self currentAccount]->tlsCaListCertificate()->isValid() == Certificate::CheckValues::PASSED) {
280 [showCAButton setHidden:NO];
281 } else
282 [showCAButton setHidden:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400283}
284
Alexandre Lision24805d52015-08-12 14:29:11 -0400285- (IBAction)certificatePathControlSingleClick:(id)sender
286{
287 NSURL* fileURL;
288 if ([sender isKindOfClass:[NSMenuItem class]]) {
289 fileURL = nil;
290 } else {
291 fileURL = [[sender clickedPathComponentCell] URL];
292 }
293 [self->certificatePathControl setURL:fileURL];
294 [self currentAccount]->setTlsCertificate([[fileURL path] UTF8String]);
295
296 auto cert = [self currentAccount]->tlsCertificate();
297
298 if (cert) {
299 [showUserCertButton setHidden:!(cert->isValid() == Certificate::CheckValues::PASSED)];
300 [pvkContainer setHidden:!cert->requirePrivateKey()];
301 } else {
302 [showUserCertButton setHidden:YES];
303 [pvkContainer setHidden:YES];
304 }
305
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400306}
307
Alexandre Lision24805d52015-08-12 14:29:11 -0400308- (IBAction)pvkFilePathControlSingleClick:(id)sender
309{
310 NSURL* fileURL;
311 if ([sender isKindOfClass:[NSMenuItem class]]) {
312 fileURL = nil;
313 } else {
314 fileURL = [[sender clickedPathComponentCell] URL];
315 }
316 [self currentAccount]->setTlsPrivateKey([[fileURL path] UTF8String]);
317 if([self currentAccount]->tlsCertificate()->requirePrivateKeyPassword()) {
318 [pvkPasswordField setHidden:NO];
319 } else {
320 [pvkPasswordField setHidden:YES];
321 }
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400322}
323
324- (IBAction)showCA:(id)sender
325{
326 certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400327 [certificateWC setCertificate:[self currentAccount]->tlsCaListCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400328 [self.view.window beginSheet:certificateWC.window completionHandler:nil];
329}
330
331- (IBAction)showEndpointCertificate:(id)sender
332{
333 certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400334 [certificateWC setCertificate:[self currentAccount]->tlsCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400335 [self.view.window beginSheet:certificateWC.window completionHandler:nil];}
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400336
337/*
338 Delegate method of NSPathControl to determine how the NSOpenPanel will look/behave.
339 */
340- (void)pathControl:(NSPathControl *)pathControl willDisplayOpenPanel:(NSOpenPanel *)openPanel
341{
342 NSLog(@"willDisplayOpenPanel");
343 [openPanel setAllowsMultipleSelection:NO];
344 [openPanel setCanChooseDirectories:NO];
345 [openPanel setCanChooseFiles:YES];
346 [openPanel setResolvesAliases:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400347
Alexandre Lision24805d52015-08-12 14:29:11 -0400348 if(pathControl == caListPathControl) {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400349 [openPanel setTitle:NSLocalizedString(@"Choose a CA list", @"Open panel title")];
Alexandre Lision24805d52015-08-12 14:29:11 -0400350 } else if (pathControl == certificatePathControl) {
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400351 [openPanel setTitle:NSLocalizedString(@"Choose a certificate", @"Open panel title")];
352 } else {
353 [openPanel setTitle:NSLocalizedString(@"Choose a private key file", @"Open panel title")];
354 }
355
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400356 [openPanel setPrompt:NSLocalizedString(@"Choose", @"Open panel prompt for 'Choose a file'")];
357 [openPanel setDelegate:self];
358}
359
360- (void)pathControl:(NSPathControl *)pathControl willPopUpMenu:(NSMenu *)menu
361{
Alexandre Lision24805d52015-08-12 14:29:11 -0400362 NSMenuItem *item;
363 if(pathControl == caListPathControl) {
364 item = [menu addItemWithTitle:@"Remove value" action:@selector(caListPathControlSingleClick:) keyEquivalent:@""];
365 } else if (pathControl == certificatePathControl) {
366 item = [menu addItemWithTitle:@"Remove value" action:@selector(certificatePathControlSingleClick:) keyEquivalent:@""];
367 } else {
368 item = [menu addItemWithTitle:@"Remove value" action:@selector(pvkFilePathControlSingleClick:) keyEquivalent:@""];
369 }
370 [item setTarget:self]; // or whatever target you want
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400371}
372
373#pragma mark - NSOpenSavePanelDelegate delegate methods
374
375- (void)panel:(id)sender willExpand:(BOOL)expanding
376{
377 //NSLog(@"willExpand");
378}
379
380- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
381{
382 //NSLog(@"userEnteredFilename");
383}
384
385- (void)panelSelectionDidChange:(id)sender
386{
387 //NSLog(@"panelSelectionDidChange");
388}
389
390- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
391{
392 NSLog(@"validateURL");
393 return YES;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400394}
395
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400396#pragma mark - NSMenuDelegate methods
397
398- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400399{
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400400 QModelIndex qIdx;
401
402 if([menu.title isEqualToString:@"tlsmethodlist"])
403 {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400404 qIdx = [self currentAccount]->tlsMethodModel()->index(index);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400405 [item setTitle:qIdx.data(Qt::DisplayRole).toString().toNSString()];
406 }
407 return YES;
408}
409
410- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
411{
412 if([menu.title isEqualToString:@"tlsmethodlist"])
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400413 return [self currentAccount]->tlsMethodModel()->rowCount();
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400414}
415
416#pragma mark - NSOutlineViewDelegate methods
417
418// -------------------------------------------------------------------------------
419// shouldSelectItem:item
420// -------------------------------------------------------------------------------
421- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
422{
423 return YES;
424}
425
426// -------------------------------------------------------------------------------
427// dataCellForTableColumn:tableColumn:item
428// -------------------------------------------------------------------------------
429- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item
430{
431 NSCell *returnCell = [tableColumn dataCell];
432 return returnCell;
433}
434
435// -------------------------------------------------------------------------------
436// textShouldEndEditing:fieldEditor
437// -------------------------------------------------------------------------------
438- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
439{
440 if ([[fieldEditor string] length] == 0)
441 {
442 // don't allow empty node names
443 return NO;
444 }
445 else
446 {
447 return YES;
448 }
449}
450
451// -------------------------------------------------------------------------------
452// shouldEditTableColumn:tableColumn:item
453//
454// Decide to allow the edit of the given outline view "item".
455// -------------------------------------------------------------------------------
456- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
457{
458 return NO;
459}
460
461// -------------------------------------------------------------------------------
462// outlineView:willDisplayCell:forTableColumn:item
463// -------------------------------------------------------------------------------
464- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
465{
466 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
467 if(!qIdx.isValid())
468 return;
469
470 if ([[tableColumn identifier] isEqualToString:COLUMNID_NAME])
471 {
472 cell.title = qIdx.data(Qt::DisplayRole).toString().toNSString();
473 }
474}
475
476// -------------------------------------------------------------------------------
477// outlineViewSelectionDidChange:notification
478// -------------------------------------------------------------------------------
479- (void)outlineViewSelectionDidChange:(NSNotification *)notification
480{
481 // ask the tree controller for the current selection
482 if([[treeController selectedNodes] count] > 0) {
483
484 }
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400485}
486
487@end