blob: cb4dda689677631c7a4caedf2815cdb1d7cf002f [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 Lisionf5fc4792015-03-17 09:15:43 -040050@interface AccSecurityVC ()
51
Alexandre Lision4de68ce2015-04-24 18:22:49 -040052@property NSTreeController *treeController;
53@property (unsafe_unretained) IBOutlet NSOutlineView *cipherListView;
54@property (unsafe_unretained) IBOutlet NSButton *useTLS;
55@property (unsafe_unretained) IBOutlet NSView *tlsContainer;
56@property (unsafe_unretained) IBOutlet NSSecureTextField *pvkPasswordField;
57@property (unsafe_unretained) IBOutlet NSTextField *outgoingTlsServerName;
58@property (unsafe_unretained) IBOutlet NSTextField *tlsNegotiationTimeout;
59@property (unsafe_unretained) IBOutlet NSStepper *tlsNegotiationTimeoutStepper;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040060
Alexandre Lision4de68ce2015-04-24 18:22:49 -040061@property CertificateWC* certificateWC;
62
63@property (unsafe_unretained) IBOutlet NSPathControl *caListPathControl;
64@property (unsafe_unretained) IBOutlet NSPathControl *certificatePathControl;
65@property (unsafe_unretained) IBOutlet NSPathControl *pvkPathControl;
66@property (unsafe_unretained) IBOutlet NSPopUpButton *tlsMethodList;
67@property (unsafe_unretained) IBOutlet NSButton *srtpRTPFallback;
68@property (unsafe_unretained) IBOutlet NSButton *useSRTP;
69
70@property (unsafe_unretained) IBOutlet NSButton *verifyCertAsClientButton;
71@property (unsafe_unretained) IBOutlet NSButton *verifyCertAsServerButton;
72@property (unsafe_unretained) IBOutlet NSButton *requireCertButton;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040073@end
74
75@implementation AccSecurityVC
Alexandre Lision4de68ce2015-04-24 18:22:49 -040076@synthesize treeController;
77@synthesize cipherListView;
78@synthesize certificateWC;
79@synthesize tlsContainer;
80@synthesize useTLS;
81@synthesize useSRTP;
82@synthesize srtpRTPFallback;
83@synthesize pvkPasswordField;
84@synthesize tlsNegotiationTimeout;
85@synthesize tlsNegotiationTimeoutStepper;
86@synthesize outgoingTlsServerName;
87@synthesize caListPathControl;
88@synthesize certificatePathControl;
89@synthesize pvkPathControl;
90@synthesize verifyCertAsClientButton;
91@synthesize verifyCertAsServerButton;
92@synthesize requireCertButton;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -040093
94- (void)awakeFromNib
95{
96 NSLog(@"INIT Security VC");
Alexandre Lision4de68ce2015-04-24 18:22:49 -040097 [pvkPasswordField setTag:PVK_PASSWORD_TAG];
98 [outgoingTlsServerName setTag:OUTGOING_TLS_SRV_NAME];
99 [tlsNegotiationTimeoutStepper setTag:TLS_NEGOTIATION_TAG];
100 [tlsNegotiationTimeout setTag:TLS_NEGOTIATION_TAG];
101
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400102 QObject::connect(AccountModel::instance()->selectionModel(),
103 &QItemSelectionModel::currentChanged,
104 [=](const QModelIndex &current, const QModelIndex &previous) {
105 if(!current.isValid())
106 return;
107 [self loadAccount];
108 });
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400109}
110
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400111- (Account*) currentAccount
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400112{
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400113 auto accIdx = AccountModel::instance()->selectionModel()->currentIndex();
114 return AccountModel::instance()->getAccountByModelIndex(accIdx);
115}
116
117- (void)loadAccount
118{
119 auto account = [self currentAccount];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400120
121 [self updateControlsWithTag:PVK_PASSWORD_TAG];
122 [self updateControlsWithTag:OUTGOING_TLS_SRV_NAME];
123 [self updateControlsWithTag:TLS_NEGOTIATION_TAG];
124
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400125 QModelIndex qTlsMethodIdx = [self currentAccount]->tlsMethodModel()->selectionModel()->currentIndex();
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400126 [self.tlsMethodList removeAllItems];
127 [self.tlsMethodList addItemWithTitle:qTlsMethodIdx.data(Qt::DisplayRole).toString().toNSString()];
128
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400129 treeController = [[QNSTreeController alloc] initWithQModel:[self currentAccount]->cipherModel()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400130 [treeController setAvoidsEmptySelection:NO];
131 [treeController setAlwaysUsesMultipleValuesMarker:YES];
132 [treeController setChildrenKeyPath:@"children"];
133
134 [cipherListView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
135 [cipherListView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil];
136 [cipherListView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
137
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400138 [useTLS setState:[self currentAccount]->isTlsEnabled()];
139 [tlsContainer setHidden:![self currentAccount]->isTlsEnabled()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400140
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400141 [useSRTP setState:[self currentAccount]->isSrtpEnabled()];
142 [srtpRTPFallback setState:[self currentAccount]->isSrtpRtpFallback()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400143 [srtpRTPFallback setEnabled:useSRTP.state];
144
145 NSArray * pathComponentArray = [self pathComponentArray];
146
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400147 if([self currentAccount]->tlsCaListCertificate() != nil) {
148 NSLog(@"CA ==> %@", [self currentAccount]->tlsCaListCertificate()->path().toNSURL());
149 [caListPathControl setURL:[self currentAccount]->tlsCaListCertificate()->path().toNSURL()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400150 } else {
151 [caListPathControl setURL:nil];
152 }
153
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400154 if([self currentAccount]->tlsCertificate() != nil) {
155 NSLog(@" CERT ==> %@", [self currentAccount]->tlsCertificate()->path().toNSURL());
156 [certificatePathControl setURL:[self currentAccount]->tlsCertificate()->path().toNSURL()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400157 } else {
158 [certificatePathControl setURL:nil];
159 }
160
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400161 if([self currentAccount]->tlsPrivateKeyCertificate() != nil) {
162 NSLog(@" PVK ==> %@", [self currentAccount]->tlsPrivateKeyCertificate()->path().toNSURL());
163 [pvkPathControl setURL:[self currentAccount]->tlsPrivateKeyCertificate()->path().toNSURL()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400164 } else {
165 [pvkPathControl setURL:nil];
166 }
167
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400168 [verifyCertAsServerButton setState:[self currentAccount]->isTlsVerifyServer()];
169 [verifyCertAsClientButton setState:[self currentAccount]->isTlsVerifyClient()];
170 [requireCertButton setState:[self currentAccount]->isTlsRequireClientCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400171}
172
173/*
174 Assemble a set of custom cells to display into an array to pass to the path control.
175 */
176- (NSArray *)pathComponentArray
177{
178 NSMutableArray *pathComponentArray = [[NSMutableArray alloc] init];
179
180 NSFileManager *fileManager = [[NSFileManager alloc] init];
181
182 NSURL* desktopURL = [fileManager URLForDirectory:NSDesktopDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
183 NSURL* documentsURL = [fileManager URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
184 NSURL* userURL = [fileManager URLForDirectory:NSUserDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
185
186 NSPathComponentCell *componentCell;
187
188 // Use utility method to obtain a NSPathComponentCell based on icon, title and URL.
189 componentCell = [self componentCellForType:kGenericFolderIcon withTitle:@"Desktop" URL:desktopURL];
190 [pathComponentArray addObject:componentCell];
191
192 componentCell = [self componentCellForType:kGenericFolderIcon withTitle:@"Documents" URL:documentsURL];
193 [pathComponentArray addObject:componentCell];
194
195 componentCell = [self componentCellForType:kUserFolderIcon withTitle:NSUserName() URL:userURL];
196 [pathComponentArray addObject:componentCell];
197
198 return pathComponentArray;
199}
200
201/*
202 This method is used by pathComponentArray to create a NSPathComponent cell based on icon, title and URL information.
203 Each path component needs an icon, URL and title.
204 */
205- (NSPathComponentCell *)componentCellForType:(OSType)withIconType withTitle:(NSString *)title URL:(NSURL *)url
206{
207 NSPathComponentCell *componentCell = [[NSPathComponentCell alloc] init];
208
209 NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(withIconType)];
210 [componentCell setImage:iconImage];
211 [componentCell setURL:url];
212 [componentCell setTitle:title];
213
214 return componentCell;
215}
216
217- (IBAction)chooseTlsMethod:(id)sender {
218 int index = [sender indexOfSelectedItem];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400219 QModelIndex qIdx = [self currentAccount]->tlsMethodModel()->index(index, 0);
220 [self currentAccount]->tlsMethodModel()->selectionModel()->setCurrentIndex(qIdx, QItemSelectionModel::ClearAndSelect);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400221}
222
223- (IBAction)toggleUseTLS:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400224 [self currentAccount]->setTlsEnabled([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400225 [tlsContainer setHidden:![sender state]];
226}
227
228- (IBAction)toggleUseSRTP:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400229 [self currentAccount]->setSrtpEnabled([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400230 [srtpRTPFallback setEnabled:[sender state]];
231}
232- (IBAction)toggleRTPFallback:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400233 [self currentAccount]->setSrtpRtpFallback([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400234}
235
236- (IBAction)toggleVerifyCertAsClient:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400237 [self currentAccount]->setTlsVerifyClient([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400238}
239
240- (IBAction)toggleVerifyCertServer:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400241 [self currentAccount]->setTlsVerifyServer([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400242}
243
244- (IBAction)toggleRequireCert:(id)sender {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400245 [self currentAccount]->setTlsRequireClientCertificate([sender state]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400246}
247
248- (IBAction)toggleCipher:(id)sender {
249 NSInteger row = [sender clickedRow];
250 NSTableColumn *col = [sender tableColumnWithIdentifier:COLUMNID_STATE];
251 NSButtonCell *cell = [col dataCellForRow:row];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400252 [self currentAccount]->cipherModel()->setData([self currentAccount]->cipherModel()->index(row, 0, QModelIndex()),
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400253 cell.state == NSOnState ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole);
254}
255
256- (void) updateControlsWithTag:(NSInteger) tag
257{
258 switch (tag) {
259 case PVK_PASSWORD_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400260 [pvkPasswordField setStringValue:[self currentAccount]->tlsPassword().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400261 break;
262 case OUTGOING_TLS_SRV_NAME:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400263 [outgoingTlsServerName setStringValue:[self currentAccount]->tlsServerName().toNSString()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400264 break;
265 case TLS_NEGOTIATION_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400266 [tlsNegotiationTimeout setIntegerValue:[self currentAccount]->tlsNegotiationTimeoutSec()];
267 [tlsNegotiationTimeoutStepper setIntegerValue:[self currentAccount]->tlsNegotiationTimeoutSec()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400268 break;
269 default:
270 break;
271 }
272}
273
274#pragma mark - NSTextFieldDelegate methods
275
276-(void)controlTextDidChange:(NSNotification *)notif
277{
278 NSTextField *textField = [notif object];
279 NSRange test = [[textField currentEditor] selectedRange];
280
281 [self valueDidChange:textField];
282 //FIXME: saving account lose focus because in NSTreeController we remove and reinsert row so View selction change
283 [textField.window makeFirstResponder:textField];
284 [[textField currentEditor] setSelectedRange:test];
285}
286
287- (IBAction) valueDidChange: (id) sender
288{
289 switch ([sender tag]) {
290 case PVK_PASSWORD_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400291 [self currentAccount]->setTlsPassword([[sender stringValue] UTF8String]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400292 break;
293 case OUTGOING_TLS_SRV_NAME:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400294 [self currentAccount]->setTlsServerName([[sender stringValue] UTF8String]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400295 break;
296 case TLS_NEGOTIATION_TAG:
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400297 [self currentAccount]->setTlsNegotiationTimeoutSec([sender integerValue]);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400298 break;
299 default:
300 break;
301 }
302 [self updateControlsWithTag:[sender tag]];
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400303}
304
305#pragma mark - NSPathControl delegate methods
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400306- (IBAction)caListPathControlSingleClick:(id)sender {
307 NSURL* fileURL = [[sender clickedPathComponentCell] URL];
308 NSLog(@"==> %@", fileURL);
309 [self.caListPathControl setURL:fileURL];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400310 [self currentAccount]->setTlsCaListCertificate(QUrl::fromNSURL(fileURL).toString());
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400311}
312
313- (IBAction)certificatePathControlSingleClick:(id)sender {
314 // Select that chosen component of the path.
315 NSURL* fileURL = [[sender clickedPathComponentCell] URL];
316 NSLog(@"==> %@", fileURL);
317 [self.certificatePathControl setURL:fileURL];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400318 [self currentAccount]->setTlsCertificate(QUrl::fromNSURL(fileURL).toString());
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400319}
320
321- (IBAction)pvkFilePathControlSingleClick:(id)sender {
322 NSURL* fileURL = [[sender clickedPathComponentCell] URL];
323 NSLog(@"==> %@", fileURL);
324 [self.pvkPathControl setURL:fileURL];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400325 [self currentAccount]->setTlsPrivateKeyCertificate(QUrl::fromNSURL(fileURL).toString());
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400326}
327
328- (IBAction)showCA:(id)sender
329{
330 certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400331 [certificateWC setCertificate:[self currentAccount]->tlsCaListCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400332 [self.view.window beginSheet:certificateWC.window completionHandler:nil];
333}
334
335- (IBAction)showEndpointCertificate:(id)sender
336{
337 certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"];
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400338 [certificateWC setCertificate:[self currentAccount]->tlsCertificate()];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400339 [self.view.window beginSheet:certificateWC.window completionHandler:nil];}
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400340
341/*
342 Delegate method of NSPathControl to determine how the NSOpenPanel will look/behave.
343 */
344- (void)pathControl:(NSPathControl *)pathControl willDisplayOpenPanel:(NSOpenPanel *)openPanel
345{
346 NSLog(@"willDisplayOpenPanel");
347 [openPanel setAllowsMultipleSelection:NO];
348 [openPanel setCanChooseDirectories:NO];
349 [openPanel setCanChooseFiles:YES];
350 [openPanel setResolvesAliases:YES];
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400351
352 if(pathControl == self.caListPathControl) {
353 [openPanel setTitle:NSLocalizedString(@"Choose a CA list", @"Open panel title")];
354 } else if (pathControl == self.certificatePathControl) {
355 [openPanel setTitle:NSLocalizedString(@"Choose a certificate", @"Open panel title")];
356 } else {
357 [openPanel setTitle:NSLocalizedString(@"Choose a private key file", @"Open panel title")];
358 }
359
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400360 [openPanel setPrompt:NSLocalizedString(@"Choose", @"Open panel prompt for 'Choose a file'")];
361 [openPanel setDelegate:self];
362}
363
364- (void)pathControl:(NSPathControl *)pathControl willPopUpMenu:(NSMenu *)menu
365{
366
367}
368
369#pragma mark - NSOpenSavePanelDelegate delegate methods
370
371- (void)panel:(id)sender willExpand:(BOOL)expanding
372{
373 //NSLog(@"willExpand");
374}
375
376- (NSString *)panel:(id)sender userEnteredFilename:(NSString *)filename confirmed:(BOOL)okFlag
377{
378 //NSLog(@"userEnteredFilename");
379}
380
381- (void)panelSelectionDidChange:(id)sender
382{
383 //NSLog(@"panelSelectionDidChange");
384}
385
386- (BOOL)panel:(id)sender validateURL:(NSURL *)url error:(NSError **)outError
387{
388 NSLog(@"validateURL");
389 return YES;
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400390}
391
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400392#pragma mark - NSMenuDelegate methods
393
394- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400395{
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400396 QModelIndex qIdx;
397
398 if([menu.title isEqualToString:@"tlsmethodlist"])
399 {
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400400 qIdx = [self currentAccount]->tlsMethodModel()->index(index);
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400401 [item setTitle:qIdx.data(Qt::DisplayRole).toString().toNSString()];
402 }
403 return YES;
404}
405
406- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
407{
408 if([menu.title isEqualToString:@"tlsmethodlist"])
Alexandre Lision7f3164c2015-06-12 11:45:37 -0400409 return [self currentAccount]->tlsMethodModel()->rowCount();
Alexandre Lision4de68ce2015-04-24 18:22:49 -0400410}
411
412#pragma mark - NSOutlineViewDelegate methods
413
414// -------------------------------------------------------------------------------
415// shouldSelectItem:item
416// -------------------------------------------------------------------------------
417- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
418{
419 return YES;
420}
421
422// -------------------------------------------------------------------------------
423// dataCellForTableColumn:tableColumn:item
424// -------------------------------------------------------------------------------
425- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item
426{
427 NSCell *returnCell = [tableColumn dataCell];
428 return returnCell;
429}
430
431// -------------------------------------------------------------------------------
432// textShouldEndEditing:fieldEditor
433// -------------------------------------------------------------------------------
434- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor
435{
436 if ([[fieldEditor string] length] == 0)
437 {
438 // don't allow empty node names
439 return NO;
440 }
441 else
442 {
443 return YES;
444 }
445}
446
447// -------------------------------------------------------------------------------
448// shouldEditTableColumn:tableColumn:item
449//
450// Decide to allow the edit of the given outline view "item".
451// -------------------------------------------------------------------------------
452- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
453{
454 return NO;
455}
456
457// -------------------------------------------------------------------------------
458// outlineView:willDisplayCell:forTableColumn:item
459// -------------------------------------------------------------------------------
460- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item
461{
462 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
463 if(!qIdx.isValid())
464 return;
465
466 if ([[tableColumn identifier] isEqualToString:COLUMNID_NAME])
467 {
468 cell.title = qIdx.data(Qt::DisplayRole).toString().toNSString();
469 }
470}
471
472// -------------------------------------------------------------------------------
473// outlineViewSelectionDidChange:notification
474// -------------------------------------------------------------------------------
475- (void)outlineViewSelectionDidChange:(NSNotification *)notification
476{
477 // ask the tree controller for the current selection
478 if([[treeController selectedNodes] count] > 0) {
479
480 }
Alexandre Lisionf5fc4792015-03-17 09:15:43 -0400481}
482
483@end