blob: 450e69bb896e6f0882d0bf1f30009eeda2224d93 [file] [log] [blame]
Kateryna Kostiuk13b76882017-03-30 09:18:44 -04001/*
2 * Copyright (C) 2015-2017 Savoir-faire Linux Inc.
3 * Author: Kateryna Kostiuk <kateryna.kostiuk@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
20#import "ChooseAccountVC.h"
21
22//Qt
23#import <QSize>
24#import <QtMacExtras/qmacfunctions.h>
25#import <QPixmap>
26
27//LRC
28#import <profilemodel.h>
29#import <profile.h>
30#import <person.h>
31#import <globalinstances.h>
32#import <accountmodel.h>
33#import <account.h>
34#import <QItemSelectionModel.h>
35#import <interfaces/pixmapmanipulatori.h>
Kateryna Kostiuk312f9132017-04-18 12:09:06 -040036#import <AvailableAccountModel.h>
37
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040038//RING
39#import "views/AccountMenuItemView.h"
Kateryna Kostiuka16c9862017-05-03 13:30:14 -040040#import "AccountSelectionManager.h"
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040041
42@interface ChooseAccountVC () <NSMenuDelegate>
43
44@end
45
46@implementation ChooseAccountVC {
Kateryna Kostiuk312f9132017-04-18 12:09:06 -040047
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040048 __unsafe_unretained IBOutlet NSImageView* profileImage;
49 __unsafe_unretained IBOutlet NSPopUpButton* accountSelectionButton;
Kateryna Kostiuk312f9132017-04-18 12:09:06 -040050
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040051}
52Boolean menuIsOpen;
53Boolean menuNeedsUpdate;
54NSMenu* accountsMenu;
55NSMenuItem* selectedMenuItem;
56QMetaObject::Connection accountUpdate;
Kateryna Kostiuk065aaf22017-07-07 13:04:23 -040057QMetaObject::Connection personUpdate;
Kateryna Kostiuka16c9862017-05-03 13:30:14 -040058AccountSelectionManager* accountManager;
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040059
60- (void)awakeFromNib
61{
62 [profileImage setWantsLayer: YES];
63 profileImage.layer.cornerRadius = profileImage.frame.size.width / 2;
64 profileImage.layer.masksToBounds = YES;
Kateryna Kostiuka16c9862017-05-03 13:30:14 -040065 accountManager = [[AccountSelectionManager alloc] init];
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040066
Kateryna Kostiuk065aaf22017-07-07 13:04:23 -040067 if (ProfileModel::instance().selectedProfile() && ProfileModel::instance().selectedProfile()->person()) {
68 Person* person = ProfileModel::instance().selectedProfile()->person();
69 auto photo = GlobalInstances::pixmapManipulator().contactPhoto(person, {140,140});
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040070 [profileImage setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))];
Kateryna Kostiuk065aaf22017-07-07 13:04:23 -040071 QObject::disconnect(personUpdate);
72 personUpdate = QObject::connect(person,
73 &Person::changed,
74 [=] {
75 //give time to cach to be updated and then change image
76 dispatch_time_t updateTime = dispatch_time(DISPATCH_TIME_NOW, 1);
77 dispatch_after(updateTime, dispatch_get_main_queue(), ^(void){
78 auto photo = GlobalInstances::pixmapManipulator().contactPhoto(person, {140,140});
79 [profileImage setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))];
80 });
81 });
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040082 }
Kateryna Kostiuk065aaf22017-07-07 13:04:23 -040083
Kateryna Kostiuk13b76882017-03-30 09:18:44 -040084 accountsMenu = [[NSMenu alloc] initWithTitle:@""];
85 [accountsMenu setDelegate:self];
86 accountSelectionButton.menu = accountsMenu;
87 [self update];
88
89 QObject::disconnect(accountUpdate);
90 accountUpdate = QObject::connect(&AccountModel::instance(),
Kateryna Kostiuk312f9132017-04-18 12:09:06 -040091 &AccountModel::dataChanged,
92 [=] {
93 [self update];
94 });
95 QObject::connect(AvailableAccountModel::instance().selectionModel(),
96 &QItemSelectionModel::currentChanged,
97 [self](const QModelIndex& idx){
Kateryna Kostiuka16c9862017-05-03 13:30:14 -040098 if(!idx.isValid()) {
99 return;
100 }
101 [accountManager saveAccountWithIndex:idx];
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400102 [self update];
103 });
104 QObject::connect(&AvailableAccountModel::instance(),
105 &QAbstractItemModel::rowsRemoved,
106 [self]{
107 [self update];
108 });
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400109}
110
111-(void) updateMenu {
112 [accountsMenu removeAllItems];
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400113 for (int i = 0; i < AvailableAccountModel::instance().rowCount(); i++) {
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400114
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400115 QModelIndex index = AvailableAccountModel::instance().selectionModel()->model()->index(i, 0);
116 Account* account = index.data(static_cast<int>(Account::Role::Object)).value<Account*>();
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400117 NSMenuItem* menuBarItem = [[NSMenuItem alloc]
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400118 initWithTitle:[self itemTitleForAccount:account]
119 action:NULL
120 keyEquivalent:@""];
121
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400122 menuBarItem.attributedTitle = [self attributedItemTitleForAccount:account];
123 AccountMenuItemView *itemView = [[AccountMenuItemView alloc] initWithFrame:CGRectZero];
124 [itemView.accountLabel setStringValue:account->alias().toNSString()];
125 NSString* userNameString = [self nameForAccount: account];
126 [itemView.userNameLabel setStringValue:userNameString];
Kateryna Kostiuka7248462017-04-18 16:15:31 -0400127 switch (account->protocol()) {
128 case Account::Protocol::SIP:
129 [itemView.accountTypeLabel setStringValue:@"SIP"];
130 break;
131 case Account::Protocol::RING:
132 [itemView.accountTypeLabel setStringValue:@"RING"];
133 break;
134 default:
135 break;
136 }
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400137 auto humanState = account->toHumanStateName();
138 [itemView.accountStatus setStringValue:humanState.toNSString()];
139 [menuBarItem setView:itemView];
140 [accountsMenu addItem:menuBarItem];
141 [accountsMenu addItem:[NSMenuItem separatorItem]];
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400142 }
143}
144
145-(NSString*) nameForAccount:(Account*) account {
146 auto name = account->registeredName();
147 NSString* userNameString = nullptr;
148 if (!name.isNull() && !name.isEmpty()) {
149 userNameString = name.toNSString();
150 } else {
151 userNameString = account->username().toNSString();
152 }
153 return userNameString;
154}
155
156-(NSString*) itemTitleForAccount:(Account*) account {
157 NSString* alias = account->alias().toNSString();
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400158 NSString* userNameString = [self nameForAccount: account];
Kateryna Kostiuka7248462017-04-18 16:15:31 -0400159 if([userNameString length] > 0) {
160 alias = [NSString stringWithFormat: @"%@\n", alias];
161 }
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400162 return [alias stringByAppendingString:userNameString];
163}
164
165- (NSAttributedString*) attributedItemTitleForAccount:(Account*) account {
166 NSString* alias = account->alias().toNSString();
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400167 NSString* userNameString = [self nameForAccount: account];
Kateryna Kostiuka7248462017-04-18 16:15:31 -0400168 if([userNameString length] > 0){
169 alias = [NSString stringWithFormat: @"%@\n", alias];
170 }
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400171 NSFont *fontAlias = [NSFont userFontOfSize:14.0];
172 NSFont *fontUserName = [NSFont userFontOfSize:11.0];
173 NSColor *colorAlias = [NSColor labelColor];
174 NSColor *colorAUserName = [NSColor secondaryLabelColor];
175 NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
176 paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail;
177 NSDictionary *aliasAttrs = [NSDictionary dictionaryWithObjectsAndKeys:fontAlias,NSFontAttributeName,
178 colorAlias,NSForegroundColorAttributeName,
179 paragraphStyle,NSParagraphStyleAttributeName, nil];
180 NSDictionary *userNameAttrs = [NSDictionary dictionaryWithObjectsAndKeys:fontUserName,NSFontAttributeName,
181 colorAUserName,NSForegroundColorAttributeName,
182 paragraphStyle,NSParagraphStyleAttributeName, nil];
183 NSAttributedString* attributedString = [[NSAttributedString alloc] initWithString:alias attributes:aliasAttrs];
184 NSAttributedString* attributedStringSecond= [[NSAttributedString alloc] initWithString:userNameString attributes:userNameAttrs];
185 NSMutableAttributedString *result = [[NSMutableAttributedString alloc] init];
186 [result appendAttributedString:attributedString];
187 [result appendAttributedString:attributedStringSecond];
188 return result;
189}
190
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400191-(void) update {
192 if(menuIsOpen) {
193 return;
194 }
195 [self updateMenu];
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400196 [self setPopUpButtonSelection];
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400197}
198
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400199-(void) setPopUpButtonSelection {
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400200 if(accountsMenu.itemArray.count == 0) {
201 [self.view setHidden:YES];
202 return;
203 }
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400204 [self.view setHidden:NO];
205 QModelIndex index = AvailableAccountModel::instance().selectionModel()->currentIndex();
206 Account* account = index.data(static_cast<int>(Account::Role::Object)).value<Account*>();
207 if(account == nil){
208 return;
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400209 }
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400210 [accountSelectionButton selectItemWithTitle:[self itemTitleForAccount:account]];
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400211}
212
213#pragma mark - NSPopUpButton item selection
214
215- (IBAction)itemChanged:(id)sender {
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400216 NSInteger row = [(NSPopUpButton *)sender indexOfSelectedItem] / 2;
217 QModelIndex index = AvailableAccountModel::instance().selectionModel()->model()->index(row, 0);
Kateryna Kostiuka16c9862017-05-03 13:30:14 -0400218 if(!index.isValid()) {
219 return;
220 }
Kateryna Kostiuk312f9132017-04-18 12:09:06 -0400221 AvailableAccountModel::instance().selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
Kateryna Kostiuka16c9862017-05-03 13:30:14 -0400222 [accountManager saveAccountWithIndex:index];
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400223}
224
225#pragma mark - NSMenuDelegate
226- (void)menuWillOpen:(NSMenu *)menu {
227 menuIsOpen = true;
228 // remember selected item to remove highlighting when menu is open
229 selectedMenuItem = [accountSelectionButton selectedItem];
230}
231- (void)menuDidClose:(NSMenu *)menu {
232
233 menuIsOpen = false;
234}
235
236- (void)menu:(NSMenu *)menu willHighlightItem:(nullable NSMenuItem *)item {
237 if (!selectedMenuItem || selectedMenuItem == item) {
238 return;
239 }
240 int index = [menu indexOfItem:selectedMenuItem];
241 [menu removeItemAtIndex:index];
242 [menu insertItem:selectedMenuItem atIndex:index];
243 [accountSelectionButton selectItemAtIndex:index];
244 selectedMenuItem = nil;
245}
246
Kateryna Kostiukabf4e272017-04-18 14:18:00 -0400247-(void) enable {
248 [accountSelectionButton setEnabled:YES];
249}
250-(void) disable {
251 [accountSelectionButton setEnabled:NO];
252}
253
Kateryna Kostiuk13b76882017-03-30 09:18:44 -0400254@end