diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a67c6806496b5b58c2c008bc970f91f4612b724..788d2e4fc2bd7105bff43574076c6166eec7f011 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ SET(ringclient_CONTROLLERS src/AccAdvancedVC.h src/AccSecurityVC.mm src/AccSecurityVC.h + src/CertificateWC.mm + src/CertificateWC.h src/AudioPrefsVC.mm src/AudioPrefsVC.h src/AccountsVC.mm @@ -103,7 +105,8 @@ SET(ringclient_XIBS AudioPrefs VideoPrefs PreferencesScreen - RingWizard) + RingWizard + CertificateWindow) # Icons # This part tells CMake where to find and install the file itself diff --git a/src/AccAdvancedVC.mm b/src/AccAdvancedVC.mm index d4bfeca790c10ce8f00f2c1465c7c4bc1f4791f4..1f42a78cbcbb2331968d75b62103e709a76562eb 100644 --- a/src/AccAdvancedVC.mm +++ b/src/AccAdvancedVC.mm @@ -137,22 +137,6 @@ #pragma mark - NSTextFieldDelegate methods -- (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor -{ - NSLog(@"textShouldBeginEditing"); - return YES; -} - -- (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error -{ - NSLog(@"didFailToValidatePartialString"); -} - --(void)controlTextDidBeginEditing:(NSNotification *)obj -{ - -} - -(void)controlTextDidChange:(NSNotification *)notif { NSTextField *textField = [notif object]; diff --git a/src/AccGeneralVC.mm b/src/AccGeneralVC.mm index cfb92ead7bb3b32c3df1cea02e7da4210a9b95e5..a75ad535fc1fe11b4ee02110d9978fac5f52c2d8 100644 --- a/src/AccGeneralVC.mm +++ b/src/AccGeneralVC.mm @@ -54,6 +54,8 @@ @property (assign) IBOutlet NSTextField *serverHostTextField; @property (assign) IBOutlet NSTextField *usernameTextField; @property (assign) IBOutlet NSSecureTextField *passwordTextField; +@property (assign) IBOutlet NSTextField *clearTextField; +@property (assign) IBOutlet NSButton *tryRegisterButton; @property (assign) IBOutlet NSButton *upnpButton; @property (assign) IBOutlet NSButton *autoAnswerButton; @@ -72,6 +74,7 @@ @synthesize serverHostTextField; @synthesize usernameTextField; @synthesize passwordTextField; +@synthesize clearTextField; @synthesize upnpButton; @synthesize autoAnswerButton; @synthesize userAgentButton; @@ -124,6 +127,7 @@ [self.serverHostTextField setStringValue:account->hostname().toNSString()]; [self.usernameTextField setStringValue:account->username().toNSString()]; [self.passwordTextField setStringValue:account->password().toNSString()]; + [self.clearTextField setStringValue:account->password().toNSString()]; } switch (account->protocol()) { @@ -148,6 +152,36 @@ [self.userAgentTextField setStringValue:account->userAgent().toNSString()]; } +- (IBAction)tryRegistration:(id)sender { + self.privateAccount << Account::EditAction::SAVE; +} + +- (IBAction)showPassword:(NSButton *)sender { + if (sender.state == NSOnState) { + clearTextField = [[NSTextField alloc] initWithFrame:passwordTextField.frame]; + [clearTextField setTag:passwordTextField.tag]; + [clearTextField setDelegate:self]; + [clearTextField setBounds:passwordTextField.bounds]; + [clearTextField setStringValue:passwordTextField.stringValue]; + [clearTextField becomeFirstResponder]; + [boxingParameters addSubview:clearTextField]; + [passwordTextField setHidden:YES]; + } else { + [passwordTextField setStringValue:clearTextField.stringValue]; + [passwordTextField setHidden:NO]; + [clearTextField removeFromSuperview]; + clearTextField = nil; + } +} + +/** + * Debug purpose + */ +-(void) dumpFrame:(CGRect) frame WithName:(NSString*) name +{ + NSLog(@"frame %@ : %f %f %f %f \n\n",name ,frame.origin.x, frame.origin.y, frame.size.width, frame.size.height); +} + #pragma mark - NSTextFieldDelegate methods - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor diff --git a/src/AccSecurityVC.h b/src/AccSecurityVC.h index 952a8de945be990f69ed79bbc139158c21404d72..f967c1f42ffd23188c1a69416c78034465ca107e 100644 --- a/src/AccSecurityVC.h +++ b/src/AccSecurityVC.h @@ -34,7 +34,7 @@ #import -@interface AccSecurityVC : NSViewController { +@interface AccSecurityVC : NSViewController { } diff --git a/src/AccSecurityVC.mm b/src/AccSecurityVC.mm index 6302cbead0dd1bb647b95a47b12f20b13f8521de..22320b1ae3763692a96448b529ff116e3196159d 100644 --- a/src/AccSecurityVC.mm +++ b/src/AccSecurityVC.mm @@ -29,26 +29,305 @@ */ #import "AccSecurityVC.h" +#import +#import +#import +#import +#import + +#import "QNSTreeController.h" +#import "CertificateWC.h" + +// Tags for views +#define PVK_PASSWORD_TAG 0 +#define OUTGOING_TLS_SRV_NAME 1 +#define TLS_NEGOTIATION_TAG 2 + +#define COLUMNID_NAME @"CipherNameColumn" +#define COLUMNID_STATE @"CipherStateColumn" + @interface AccSecurityVC () @property Account* privateAccount; +@property NSTreeController *treeController; +@property (unsafe_unretained) IBOutlet NSOutlineView *cipherListView; +@property (unsafe_unretained) IBOutlet NSButton *useTLS; +@property (unsafe_unretained) IBOutlet NSView *tlsContainer; +@property (unsafe_unretained) IBOutlet NSSecureTextField *pvkPasswordField; +@property (unsafe_unretained) IBOutlet NSTextField *outgoingTlsServerName; +@property (unsafe_unretained) IBOutlet NSTextField *tlsNegotiationTimeout; +@property (unsafe_unretained) IBOutlet NSStepper *tlsNegotiationTimeoutStepper; +@property CertificateWC* certificateWC; + +@property (unsafe_unretained) IBOutlet NSPathControl *caListPathControl; +@property (unsafe_unretained) IBOutlet NSPathControl *certificatePathControl; +@property (unsafe_unretained) IBOutlet NSPathControl *pvkPathControl; +@property (unsafe_unretained) IBOutlet NSPopUpButton *tlsMethodList; +@property (unsafe_unretained) IBOutlet NSButton *srtpRTPFallback; +@property (unsafe_unretained) IBOutlet NSButton *useSRTP; + +@property (unsafe_unretained) IBOutlet NSButton *verifyCertAsClientButton; +@property (unsafe_unretained) IBOutlet NSButton *verifyCertAsServerButton; +@property (unsafe_unretained) IBOutlet NSButton *requireCertButton; @end @implementation AccSecurityVC @synthesize privateAccount; +@synthesize treeController; +@synthesize cipherListView; +@synthesize certificateWC; +@synthesize tlsContainer; +@synthesize useTLS; +@synthesize useSRTP; +@synthesize srtpRTPFallback; +@synthesize pvkPasswordField; +@synthesize tlsNegotiationTimeout; +@synthesize tlsNegotiationTimeoutStepper; +@synthesize outgoingTlsServerName; +@synthesize caListPathControl; +@synthesize certificatePathControl; +@synthesize pvkPathControl; +@synthesize verifyCertAsClientButton; +@synthesize verifyCertAsServerButton; +@synthesize requireCertButton; - (void)awakeFromNib { NSLog(@"INIT Security VC"); + [pvkPasswordField setTag:PVK_PASSWORD_TAG]; + [outgoingTlsServerName setTag:OUTGOING_TLS_SRV_NAME]; + [tlsNegotiationTimeoutStepper setTag:TLS_NEGOTIATION_TAG]; + [tlsNegotiationTimeout setTag:TLS_NEGOTIATION_TAG]; + } - (void)loadAccount:(Account *)account { privateAccount = account; + + [self updateControlsWithTag:PVK_PASSWORD_TAG]; + [self updateControlsWithTag:OUTGOING_TLS_SRV_NAME]; + [self updateControlsWithTag:TLS_NEGOTIATION_TAG]; + + QModelIndex qTlsMethodIdx = privateAccount->tlsMethodModel()->selectionModel()->currentIndex(); + [self.tlsMethodList removeAllItems]; + [self.tlsMethodList addItemWithTitle:qTlsMethodIdx.data(Qt::DisplayRole).toString().toNSString()]; + + treeController = [[QNSTreeController alloc] initWithQModel:privateAccount->cipherModel()]; + [treeController setAvoidsEmptySelection:NO]; + [treeController setAlwaysUsesMultipleValuesMarker:YES]; + [treeController setChildrenKeyPath:@"children"]; + + [cipherListView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil]; + [cipherListView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil]; + [cipherListView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil]; + + [useTLS setState:privateAccount->isTlsEnabled()]; + [tlsContainer setHidden:!privateAccount->isTlsEnabled()]; + + [useSRTP setState:privateAccount->isSrtpEnabled()]; + [srtpRTPFallback setState:privateAccount->isSrtpRtpFallback()]; + [srtpRTPFallback setEnabled:useSRTP.state]; + + NSArray * pathComponentArray = [self pathComponentArray]; + + if(privateAccount->tlsCaListCertificate() != nil) { + NSLog(@"CA ==> %@", privateAccount->tlsCaListCertificate()->path().toNSURL()); + [caListPathControl setURL:privateAccount->tlsCaListCertificate()->path().toNSURL()]; + } else { + [caListPathControl setURL:nil]; + } + + if(privateAccount->tlsCertificate() != nil) { + NSLog(@" CERT ==> %@", privateAccount->tlsCertificate()->path().toNSURL()); + [certificatePathControl setURL:privateAccount->tlsCertificate()->path().toNSURL()]; + } else { + [certificatePathControl setURL:nil]; + } + + if(privateAccount->tlsPrivateKeyCertificate() != nil) { + NSLog(@" PVK ==> %@", privateAccount->tlsPrivateKeyCertificate()->path().toNSURL()); + [pvkPathControl setURL:privateAccount->tlsPrivateKeyCertificate()->path().toNSURL()]; + } else { + [pvkPathControl setURL:nil]; + } + + [verifyCertAsServerButton setState:privateAccount->isTlsVerifyServer()]; + [verifyCertAsClientButton setState:privateAccount->isTlsVerifyClient()]; + [requireCertButton setState:privateAccount->isTlsRequireClientCertificate()]; +} + +/* + Assemble a set of custom cells to display into an array to pass to the path control. + */ +- (NSArray *)pathComponentArray +{ + NSMutableArray *pathComponentArray = [[NSMutableArray alloc] init]; + + NSFileManager *fileManager = [[NSFileManager alloc] init]; + + NSURL* desktopURL = [fileManager URLForDirectory:NSDesktopDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + NSURL* documentsURL = [fileManager URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + NSURL* userURL = [fileManager URLForDirectory:NSUserDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + + NSPathComponentCell *componentCell; + + // Use utility method to obtain a NSPathComponentCell based on icon, title and URL. + componentCell = [self componentCellForType:kGenericFolderIcon withTitle:@"Desktop" URL:desktopURL]; + [pathComponentArray addObject:componentCell]; + + componentCell = [self componentCellForType:kGenericFolderIcon withTitle:@"Documents" URL:documentsURL]; + [pathComponentArray addObject:componentCell]; + + componentCell = [self componentCellForType:kUserFolderIcon withTitle:NSUserName() URL:userURL]; + [pathComponentArray addObject:componentCell]; + + return pathComponentArray; +} + +/* + This method is used by pathComponentArray to create a NSPathComponent cell based on icon, title and URL information. + Each path component needs an icon, URL and title. + */ +- (NSPathComponentCell *)componentCellForType:(OSType)withIconType withTitle:(NSString *)title URL:(NSURL *)url +{ + NSPathComponentCell *componentCell = [[NSPathComponentCell alloc] init]; + + NSImage *iconImage = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(withIconType)]; + [componentCell setImage:iconImage]; + [componentCell setURL:url]; + [componentCell setTitle:title]; + + return componentCell; +} + +- (IBAction)chooseTlsMethod:(id)sender { + int index = [sender indexOfSelectedItem]; + QModelIndex qIdx = privateAccount->tlsMethodModel()->index(index, 0); + privateAccount->tlsMethodModel()->selectionModel()->setCurrentIndex(qIdx, QItemSelectionModel::ClearAndSelect); +} + +- (IBAction)toggleUseTLS:(id)sender { + privateAccount->setTlsEnabled([sender state]); + [tlsContainer setHidden:![sender state]]; +} + +- (IBAction)toggleUseSRTP:(id)sender { + privateAccount->setSrtpEnabled([sender state]); + [srtpRTPFallback setEnabled:[sender state]]; +} +- (IBAction)toggleRTPFallback:(id)sender { + privateAccount->setSrtpRtpFallback([sender state]); +} + +- (IBAction)toggleVerifyCertAsClient:(id)sender { + privateAccount->setTlsVerifyClient([sender state]); +} + +- (IBAction)toggleVerifyCertServer:(id)sender { + privateAccount->setTlsVerifyServer([sender state]); +} + +- (IBAction)toggleRequireCert:(id)sender { + privateAccount->setTlsRequireClientCertificate([sender state]); +} + +- (IBAction)toggleCipher:(id)sender { + NSInteger row = [sender clickedRow]; + NSTableColumn *col = [sender tableColumnWithIdentifier:COLUMNID_STATE]; + NSButtonCell *cell = [col dataCellForRow:row]; + privateAccount->cipherModel()->setData(privateAccount->cipherModel()->index(row, 0, QModelIndex()), + cell.state == NSOnState ? Qt::Unchecked : Qt::Checked, Qt::CheckStateRole); +} + +- (void) updateControlsWithTag:(NSInteger) tag +{ + switch (tag) { + case PVK_PASSWORD_TAG: + [pvkPasswordField setStringValue:privateAccount->tlsPassword().toNSString()]; + break; + case OUTGOING_TLS_SRV_NAME: + [outgoingTlsServerName setStringValue:privateAccount->tlsServerName().toNSString()]; + break; + case TLS_NEGOTIATION_TAG: + [tlsNegotiationTimeout setIntegerValue:privateAccount->tlsNegotiationTimeoutSec()]; + [tlsNegotiationTimeoutStepper setIntegerValue:privateAccount->tlsNegotiationTimeoutSec()]; + break; + default: + break; + } +} + +#pragma mark - NSTextFieldDelegate methods + +-(void)controlTextDidChange:(NSNotification *)notif +{ + NSTextField *textField = [notif object]; + NSRange test = [[textField currentEditor] selectedRange]; + + [self valueDidChange:textField]; + //FIXME: saving account lose focus because in NSTreeController we remove and reinsert row so View selction change + [textField.window makeFirstResponder:textField]; + [[textField currentEditor] setSelectedRange:test]; +} + +- (IBAction) valueDidChange: (id) sender +{ + switch ([sender tag]) { + case PVK_PASSWORD_TAG: + privateAccount->setTlsPassword([[sender stringValue] UTF8String]); + break; + case OUTGOING_TLS_SRV_NAME: + privateAccount->setTlsServerName([[sender stringValue] UTF8String]); + break; + case TLS_NEGOTIATION_TAG: + privateAccount->setTlsNegotiationTimeoutSec([sender integerValue]); + break; + default: + break; + } + [self updateControlsWithTag:[sender tag]]; } #pragma mark - NSPathControl delegate methods +- (IBAction)caListPathControlSingleClick:(id)sender { + NSURL* fileURL = [[sender clickedPathComponentCell] URL]; + NSLog(@"==> %@", fileURL); + [self.caListPathControl setURL:fileURL]; + privateAccount->setTlsCaListCertificate(QUrl::fromNSURL(fileURL).toString()); +} + +- (IBAction)certificatePathControlSingleClick:(id)sender { + // Select that chosen component of the path. + NSURL* fileURL = [[sender clickedPathComponentCell] URL]; + NSLog(@"==> %@", fileURL); + [self.certificatePathControl setURL:fileURL]; + privateAccount->setTlsCertificate(QUrl::fromNSURL(fileURL).toString()); +} + +- (IBAction)pvkFilePathControlSingleClick:(id)sender { + NSURL* fileURL = [[sender clickedPathComponentCell] URL]; + NSLog(@"==> %@", fileURL); + [self.pvkPathControl setURL:fileURL]; + privateAccount->setTlsPrivateKeyCertificate(QUrl::fromNSURL(fileURL).toString()); + + + // qDebug() << "TEST" << privateAccount->tlsPrivateKeyCertificate()->hasPrivateKey(); +} + +- (IBAction)showCA:(id)sender +{ + certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"]; + [certificateWC setCertificate:privateAccount->tlsCaListCertificate()]; + [self.view.window beginSheet:certificateWC.window completionHandler:nil]; +} + +- (IBAction)showEndpointCertificate:(id)sender +{ + certificateWC = [[CertificateWC alloc] initWithWindowNibName:@"CertificateWindow"]; + [certificateWC setCertificate:privateAccount->tlsCertificate()]; + [self.view.window beginSheet:certificateWC.window completionHandler:nil];} /* Delegate method of NSPathControl to determine how the NSOpenPanel will look/behave. @@ -60,7 +339,16 @@ [openPanel setCanChooseDirectories:NO]; [openPanel setCanChooseFiles:YES]; [openPanel setResolvesAliases:YES]; - [openPanel setTitle:NSLocalizedString(@"Choose a file", @"Open panel title")]; + + if(pathControl == self.caListPathControl) { + [openPanel setTitle:NSLocalizedString(@"Choose a CA list", @"Open panel title")]; + } else if (pathControl == self.certificatePathControl) { + [openPanel setTitle:NSLocalizedString(@"Choose a certificate", @"Open panel title")]; + } else { + [openPanel setTitle:NSLocalizedString(@"Choose a private key file", @"Open panel title")]; + } + + [openPanel setPrompt:NSLocalizedString(@"Choose", @"Open panel prompt for 'Choose a file'")]; [openPanel setDelegate:self]; } @@ -91,12 +379,97 @@ { NSLog(@"validateURL"); return YES; +} + +#pragma mark - NSMenuDelegate methods + +- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel +{ + QModelIndex qIdx; + + if([menu.title isEqualToString:@"tlsmethodlist"]) + { + qIdx = privateAccount->tlsMethodModel()->index(index); + [item setTitle:qIdx.data(Qt::DisplayRole).toString().toNSString()]; + } + return YES; +} + +- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu +{ + if([menu.title isEqualToString:@"tlsmethodlist"]) + return privateAccount->tlsMethodModel()->rowCount(); +} + +#pragma mark - NSOutlineViewDelegate methods + +// ------------------------------------------------------------------------------- +// shouldSelectItem:item +// ------------------------------------------------------------------------------- +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item; +{ + return YES; +} +// ------------------------------------------------------------------------------- +// dataCellForTableColumn:tableColumn:item +// ------------------------------------------------------------------------------- +- (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + NSCell *returnCell = [tableColumn dataCell]; + return returnCell; } -- (void)panel:(id)sender didChangeToDirectoryURL:(NSURL *)url +// ------------------------------------------------------------------------------- +// textShouldEndEditing:fieldEditor +// ------------------------------------------------------------------------------- +- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor { - //NSLog(@"didChangeToDirectoryURL"); + if ([[fieldEditor string] length] == 0) + { + // don't allow empty node names + return NO; + } + else + { + return YES; + } +} + +// ------------------------------------------------------------------------------- +// shouldEditTableColumn:tableColumn:item +// +// Decide to allow the edit of the given outline view "item". +// ------------------------------------------------------------------------------- +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + return NO; +} + +// ------------------------------------------------------------------------------- +// outlineView:willDisplayCell:forTableColumn:item +// ------------------------------------------------------------------------------- +- (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell*)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item +{ + QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)]; + if(!qIdx.isValid()) + return; + + if ([[tableColumn identifier] isEqualToString:COLUMNID_NAME]) + { + cell.title = qIdx.data(Qt::DisplayRole).toString().toNSString(); + } +} + +// ------------------------------------------------------------------------------- +// outlineViewSelectionDidChange:notification +// ------------------------------------------------------------------------------- +- (void)outlineViewSelectionDidChange:(NSNotification *)notification +{ + // ask the tree controller for the current selection + if([[treeController selectedNodes] count] > 0) { + + } } @end diff --git a/src/AccountsVC.mm b/src/AccountsVC.mm index 3bbd086d933c1e1070861bfc4e526213f9f180d6..42ae01b62fb880d35e6a6d4b02f5bcc66021dd46 100644 --- a/src/AccountsVC.mm +++ b/src/AccountsVC.mm @@ -113,12 +113,9 @@ public: [accountsListView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil]; [accountsListView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil]; - QObject::connect(AccountModel::instance(), &QAbstractItemModel::dataChanged, [=](const QModelIndex &topLeft, const QModelIndex &bottomRight) { - NSLog(@"data changed %d, %d", topLeft.row(), bottomRight.row()); - [accountsListView reloadDataForRowIndexes: [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(topLeft.row(), bottomRight.row() + 1)] columnIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, accountsListView.tableColumns.count)]]; @@ -208,8 +205,8 @@ public: [configPanels insertTabViewItem:generalTabItem atIndex:0]; [configPanels insertTabViewItem:audioTabItem atIndex:1]; [configPanels insertTabViewItem:videoTabItem atIndex:2]; - //[configPanels insertTabViewItem:advancedTabItem atIndex:3]; - //[configPanels insertTabViewItem:securityTabItem atIndex:4]; + [configPanels insertTabViewItem:advancedTabItem atIndex:3]; + [configPanels insertTabViewItem:securityTabItem atIndex:4]; [self.generalVC loadAccount:acc]; [self.audioVC loadAccount:acc]; @@ -270,6 +267,7 @@ public: Account* toToggle = AccountModel::instance()->getAccountByModelIndex(accIdx); NSButtonCell *cell = [col dataCellForRow:row]; toToggle->setEnabled(cell.state == NSOnState ? NO : YES); + toToggle << Account::EditAction::SAVE; } } @@ -288,7 +286,17 @@ public: // ------------------------------------------------------------------------------- - (NSCell *)outlineView:(NSOutlineView *)outlineView dataCellForTableColumn:(NSTableColumn *)tableColumn item:(id)item { - NSCell *returnCell = [tableColumn dataCell]; + NSCell *returnCell; + + QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)]; + // Prevent user from enabling/disabling IP2IP account + if ([[tableColumn identifier] isEqualToString:COLUMNID_ENABLE] && + AccountModel::instance()->ip2ip()->index() == qIdx) { + + returnCell = [[NSCell alloc] init]; + } else { + returnCell = [tableColumn dataCell]; + } return returnCell; } @@ -331,25 +339,30 @@ public: { cell.title = AccountModel::instance()->data(qIdx, Qt::DisplayRole).toString().toNSString(); } else if([[tableColumn identifier] isEqualToString:COLUMNID_STATE]) { - Account::RegistrationState state = qvariant_cast(AccountModel::instance()->data(qIdx, (int)Account::Role::RegistrationState)); + NSTextFieldCell* stateCell = cell; + Account::RegistrationState state = qvariant_cast(qIdx.data((int)Account::Role::RegistrationState)); switch (state) { case Account::RegistrationState::READY: - [cell setTitle:@"Ready"]; + [stateCell setTextColor:[NSColor colorWithCalibratedRed:116/255.0 green:179/255.0 blue:93/255.0 alpha:1.0]]; + [stateCell setTitle:@"Ready"]; break; case Account::RegistrationState::TRYING: - [cell setTitle:@"Trying..."]; + [stateCell setTextColor:[NSColor redColor]]; + [stateCell setTitle:@"Trying..."]; break; case Account::RegistrationState::UNREGISTERED: - [cell setTitle:@"Unregistered"]; + [stateCell setTextColor:[NSColor blackColor]]; + [stateCell setTitle:@"Unregistered"]; break; case Account::RegistrationState::ERROR: - [cell setTitle:@"Error"]; + [stateCell setTextColor:[NSColor redColor]]; + [stateCell setTitle:@"Error"]; break; default: break; } } else if([[tableColumn identifier] isEqualToString:COLUMNID_ENABLE]) { - [cell setState:AccountModel::instance()->data(qIdx, Qt::CheckStateRole).value()]; + [cell setState:qIdx.data(Qt::CheckStateRole).value()]; } } @@ -396,7 +409,7 @@ public: { QModelIndex proxyIdx = proxyProtocolModel->index(index, 0); QModelIndex qIdx = AccountModel::instance()->protocolModel()->index(proxyProtocolModel->mapToSource(proxyIdx).row()); - [item setTitle:AccountModel::instance()->protocolModel()->data(qIdx, Qt::DisplayRole).toString().toNSString()]; + [item setTitle:qIdx.data(Qt::DisplayRole).toString().toNSString()]; return YES; } diff --git a/src/AudioPrefsVC.mm b/src/AudioPrefsVC.mm index 16700a6b93c4f26487e2cbee6c56d9e26acfe1cc..cd18ed062e821b2be25e7640df73342723a10849 100644 --- a/src/AudioPrefsVC.mm +++ b/src/AudioPrefsVC.mm @@ -73,6 +73,8 @@ if([[Audio::Settings::instance()->recordPath().toNSURL() absoluteString] isEqualToString:@""]) { NSArray * pathComponentArray = [self pathComponentArray]; [recordingsPathControl setPathComponentCells:pathComponentArray]; + } else { + [recordingsPathControl setURL:Audio::Settings::instance()->recordPath().toNSURL()]; } } diff --git a/src/CertificateWC.h b/src/CertificateWC.h new file mode 100644 index 0000000000000000000000000000000000000000..ea45bfbdfde7e108f8c4e68d26ba023786e6bee7 --- /dev/null +++ b/src/CertificateWC.h @@ -0,0 +1,17 @@ +// +// CertificateWC.h +// Ring +// +// Created by Alexandre Lision on 2015-04-28. +// +// + +#import + +#import + +@interface CertificateWC : NSWindowController + +- (void) setCertificate:(Certificate*) cert; + +@end diff --git a/src/CertificateWC.mm b/src/CertificateWC.mm new file mode 100644 index 0000000000000000000000000000000000000000..8d76a603929ed9131460a976d67e8caf60db101d --- /dev/null +++ b/src/CertificateWC.mm @@ -0,0 +1,29 @@ +// +// CertificateWC.m +// Ring +// +// Created by Alexandre Lision on 2015-04-28. +// +// + +#import "CertificateWC.h" + +@implementation CertificateWC + +- (void)windowDidLoad { + [super windowDidLoad]; +} + +- (void) setCertificate:(Certificate*) cert +{ + NSLog(@"CertificateWC loaded"); +} + +- (IBAction)closePanel:(id)sender +{ + [NSApp endSheet:self.window]; + [self.window orderOut:self]; +} + + +@end diff --git a/src/GeneralPrefsVC.mm b/src/GeneralPrefsVC.mm index 4bc2b3bc1368e30e95cb70388f499210b055d589..46085286bb4637211a491206ad0273d479a72e4f 100644 --- a/src/GeneralPrefsVC.mm +++ b/src/GeneralPrefsVC.mm @@ -35,18 +35,21 @@ @interface GeneralPrefsVC () @property (assign) IBOutlet NSTextField *historyChangedLabel; +@property (assign) IBOutlet NSView *advancedGeneralSettings; @end -@implementation GeneralPrefsVC { - -} +@implementation GeneralPrefsVC @synthesize historyChangedLabel; +@synthesize advancedGeneralSettings; - (void)loadView { [super loadView]; [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:Preferences::HistoryLimit options:NSKeyValueObservingOptionNew context:NULL]; + [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:Preferences::ShowAdvanced options:NSKeyValueObservingOptionNew context:NULL]; + + [advancedGeneralSettings setHidden:![[NSUserDefaults standardUserDefaults] boolForKey:Preferences::ShowAdvanced]]; } - (IBAction)clearHistory:(id)sender { @@ -58,8 +61,11 @@ -(void)observeValueForKeyPath:(NSString *)aKeyPath ofObject:(id)anObject change:(NSDictionary *)aChange context:(void *)aContext { - NSLog(@"VALUE CHANGED"); - [historyChangedLabel setHidden:NO]; + if (aKeyPath == Preferences::HistoryLimit) { + [historyChangedLabel setHidden:NO]; + } else if (aKeyPath == Preferences::ShowAdvanced) { + [advancedGeneralSettings setHidden:[[aChange objectForKey: NSKeyValueChangeNewKey] boolValue]]; + } } @end diff --git a/src/PreferencesVC.h b/src/PreferencesVC.h index 583e2e596513bd6da2713c14ca9c994470f4f922..e763caad07bef30dab12a9aa8edd23ab09ac9d79 100644 --- a/src/PreferencesVC.h +++ b/src/PreferencesVC.h @@ -34,13 +34,13 @@ @interface PreferencesVC : NSViewController -- (void) close; @property (nonatomic, assign) NSViewController *currentVC; @property (nonatomic, assign) NSViewController *accountsPrefsVC; @property (nonatomic, assign) NSViewController *generalPrefsVC; @property (nonatomic, assign) NSViewController *audioPrefsVC; @property (nonatomic, assign) NSViewController *videoPrefsVC; +- (void) close; - (void)displayGeneral:(NSToolbarItem *)sender; - (void)displayAudio:(NSToolbarItem *)sender; - (void)displayAncrage:(NSToolbarItem *)sender; diff --git a/src/RingWindowController.mm b/src/RingWindowController.mm index 72fdda5ce52f7a8cab3a3e269fa42d82f95539a4..f708f7c7540c64fb8052bc6670ed84835b83907f 100644 --- a/src/RingWindowController.mm +++ b/src/RingWindowController.mm @@ -202,7 +202,6 @@ static NSString* const kCallButtonIdentifer = @"CallButtonIdentifier"; - (IBAction)placeCall:(id)sender { Call* c = CallModel::instance()->dialingCall(); - // check for a valid ring hash NSCharacterSet *hexSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"]; BOOL valid = [[[callField stringValue] stringByTrimmingCharactersInSet:hexSet] isEqualToString:@""]; diff --git a/ui/AccAdvanced.xib b/ui/AccAdvanced.xib index 5edd143ff61121daae0b96186e13219ec1d4cbee..291a17d17cf8799cb244bc48bd981580d30d1efc 100644 --- a/ui/AccAdvanced.xib +++ b/ui/AccAdvanced.xib @@ -1,5 +1,5 @@ - + @@ -44,15 +44,16 @@ - + - + + @@ -105,7 +106,7 @@ - + @@ -113,6 +114,9 @@ + + + @@ -142,7 +146,7 @@ - + @@ -150,6 +154,9 @@ + + + @@ -168,7 +175,7 @@ - + @@ -176,6 +183,9 @@ + + + @@ -202,7 +212,7 @@ - + @@ -210,6 +220,9 @@ + + + @@ -228,7 +241,7 @@ - + @@ -236,6 +249,9 @@ + + + @@ -255,7 +271,7 @@ - + @@ -309,6 +325,14 @@ + + + + + + + + diff --git a/ui/AccGeneral.xib b/ui/AccGeneral.xib index 4e8f5167e739c0a008b27e8eafc633d197a24209..b4d5ad2d8b1152ee223fb463dc9e6b6e53e37247 100644 --- a/ui/AccGeneral.xib +++ b/ui/AccGeneral.xib @@ -1,8 +1,7 @@ - + - - + @@ -147,6 +146,26 @@ + + diff --git a/ui/AccSecurity.xib b/ui/AccSecurity.xib index 26fd39d19b5346520af55a0fbd0175414f3cb56f..30b8bc620e6cabcf3ac9d37132e97bacb4188d1f 100644 --- a/ui/AccSecurity.xib +++ b/ui/AccSecurity.xib @@ -1,227 +1,337 @@ - + - + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - NSAllRomanInputSourcesLocaleIdentifier - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + NSAllRomanInputSourcesLocaleIdentifier + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + diff --git a/ui/AccVideo.xib b/ui/AccVideo.xib index 66ca7e6826599c641d698518d14159f248335d93..d6b02dbd0966f7123fae0fbd585ca4096ef84398 100644 --- a/ui/AccVideo.xib +++ b/ui/AccVideo.xib @@ -1,8 +1,7 @@ - + - - + @@ -30,7 +29,7 @@ - + @@ -140,16 +139,16 @@ + + + + + + + + - - - - - - - - diff --git a/ui/AudioPrefs.xib b/ui/AudioPrefs.xib index d40e68c23377914b982ee7123b3f04bb7b22836e..3dcd213eb155362640d80d312afc8f1e28f3f186 100644 --- a/ui/AudioPrefs.xib +++ b/ui/AudioPrefs.xib @@ -1,5 +1,5 @@ - + @@ -72,17 +72,6 @@ - - - - - - - - - - - @@ -132,6 +121,17 @@ + + + + + + + + + + + diff --git a/ui/CertificateWindow.xib b/ui/CertificateWindow.xib new file mode 100644 index 0000000000000000000000000000000000000000..107b06f386478abd307ba9eb316b21821fde203f --- /dev/null +++ b/ui/CertificateWindow.xib @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/GeneralPrefs.xib b/ui/GeneralPrefs.xib index 83d3111956a3622cceaeb7f978a962d73e272462..362972e214f17211e791d6af98d3b46e395cb008 100644 --- a/ui/GeneralPrefs.xib +++ b/ui/GeneralPrefs.xib @@ -1,11 +1,12 @@ - + - + + @@ -13,11 +14,11 @@ - + - + @@ -25,7 +26,7 @@ - + @@ -33,7 +34,7 @@ - + @@ -61,21 +62,21 @@ - + - + @@ -86,7 +87,7 @@ - + @@ -94,7 +95,7 @@ + + + + + + + + + - +