blob: 58fe50eceaf772ad163208ed7aa4fe4992e881e9 [file] [log] [blame]
/*
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "ChooseContactVC.h"
#import "views/RingTableView.h"
#import "views/HoverTableRowView.h"
#import "utils.h"
#import "delegates/ImageManipulationDelegate.h"
//LRC
#import <globalinstances.h>
#import <api/conversationmodel.h>
#import <api/account.h>
#import <api/newaccountmodel.h>
//Qt
#import <QtMacExtras/qmacfunctions.h>
#import <QPixmap>
@interface ChooseContactVC () {
__unsafe_unretained IBOutlet RingTableView* contactsView;
__unsafe_unretained IBOutlet RingTableView* callsView;
__unsafe_unretained IBOutlet NSSearchField* searchField;
__unsafe_unretained IBOutlet NSLayoutConstraint* contactsViewHeightConstraint;
__unsafe_unretained IBOutlet NSLayoutConstraint* calsViewHeightConstraint;
__unsafe_unretained IBOutlet NSStackView* callsContainer;
__unsafe_unretained IBOutlet NSStackView* contactsContainer;
__unsafe_unretained IBOutlet NSTextField* contactsLabel;
}
@end
@implementation ChooseContactVC
lrc::api::ConversationModel* convModel;
QString currentConversation;
QMap<lrc::api::ConferenceableItem, lrc::api::ConferenceableValue> values;
// Tags for views
NSInteger const IMAGE_TAG = 100;
NSInteger const DISPLAYNAME_TAG = 200;
NSInteger const RING_ID_LABEL = 300;
NSInteger const PRESENCE_TAG = 400;
NSInteger const ROW_HEIGHT = 60;
NSInteger const MINIMUM_TABLE_SIZE = 0;
NSInteger const NORMAL_TABLE_SIZE = 120;
NSInteger const MAXIMUM_TABLE_SIZE = 240;
- (void)controlTextDidChange:(NSNotification *) notification
{
values = convModel->getConferenceableConversations(currentConversation, QString::fromNSString(searchField.stringValue));
[self reloadView];
}
- (void) reloadView
{
[callsView reloadData];
[contactsView reloadData];
auto callsSize = [callsView numberOfRows] * ROW_HEIGHT;
auto contactsSize = [contactsView numberOfRows] * ROW_HEIGHT;
if (callsSize >= NORMAL_TABLE_SIZE) {
if (contactsSize >= NORMAL_TABLE_SIZE) {
contactsViewHeightConstraint.constant = NORMAL_TABLE_SIZE;
calsViewHeightConstraint.constant = NORMAL_TABLE_SIZE;
} else {
contactsViewHeightConstraint.constant = contactsSize;
calsViewHeightConstraint.constant = MAXIMUM_TABLE_SIZE - contactsSize;
}
} else if (callsSize == MINIMUM_TABLE_SIZE) {
// when call stack view is hidden add 35 to avoid controller size changes
// 17 - call label height + 8*2 stack view margins
contactsViewHeightConstraint.constant = MAXIMUM_TABLE_SIZE + 35;
calsViewHeightConstraint.constant = callsSize;
} else {
contactsViewHeightConstraint.constant = MAXIMUM_TABLE_SIZE - callsSize;
calsViewHeightConstraint.constant = callsSize;
}
[callsContainer setHidden: callsSize == 0];
[contactsLabel setHidden: contactsSize == 0];
}
-(void)viewDidLoad {
[super viewDidLoad];
[self reloadView];
}
- (void)setConversationModel:(lrc::api::ConversationModel *)conversationModel
andCurrentConversation:(const QString&)conversation
{
convModel = conversationModel;
if (convModel == nil) {
return;
}
currentConversation = conversation;
values = convModel->getConferenceableConversations(currentConversation, "");
[self reloadView];
}
#pragma mark - NSTableViewDelegate methods
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row
{
return YES;
}
- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
return NO;
}
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSInteger row = [notification.object selectedRow];
NSTableView *table = notification.object;
NSInteger rows = [table numberOfRows];
for (int i = 0; i< rows; i++) {
HoverTableRowView* cellRowView = [table rowViewAtRow:i makeIfNecessary: NO];
[cellRowView drawSelection: (i == row)];
}
if (row == -1 || convModel == nil)
return;
QVector<QVector<lrc::api::AccountConversation>> conversations = table == callsView ? values.value(lrc::api::ConferenceableItem::CALL) : values.value(lrc::api::ConferenceableItem::CONTACT);
if (conversations.size() < row) {
return;
}
QVector<lrc::api::AccountConversation> participants = conversations[row];
if (participants.isEmpty()) {
return;
}
auto conversation = participants[0];
auto accountID = conversation.accountId;
auto convID = conversation.convId;
auto convMod = convModel->owner.accountModel->getAccountInfo(accountID).conversationModel.get();
auto conversationInfo = getConversationFromUid(convID, *convMod, false);
auto convQueue = convModel->owner.accountModel->getAccountInfo(accountID).conversationModel.get()->allFilteredConversations();
if (conversationInfo == convQueue.end()) {
return;
}
if (table == callsView) {
auto callID = conversationInfo->confId.isEmpty() ? conversationInfo->callId : conversationInfo->confId;
[self.delegate joinCall: callID];
} else if (table == contactsView) {
auto uid = conversationInfo->participants.front();
[self.delegate callToContact:uid convUID:convModel->filteredConversation(row).uid];
}
}
- (NSTableRowView *)tableView:(NSTableView *)tableView rowViewForRow:(NSInteger)row
{
HoverTableRowView *howerRow = [tableView makeViewWithIdentifier:@"HoverRowView" owner:nil];
[howerRow setBlurType:7];
return howerRow;
}
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if (convModel == nil)
return nil;
QVector<QVector<lrc::api::AccountConversation>> allConversations;
if (tableView == callsView && convModel != nullptr) {
allConversations = values.value(lrc::api::ConferenceableItem::CALL);
} else if (tableView == contactsView && convModel != nullptr) {
allConversations = values.value(lrc::api::ConferenceableItem::CONTACT);
}
if (allConversations.size() < row) {
return nil;
}
QVector<lrc::api::AccountConversation> conversations = allConversations[row];
if (conversations.size() < 1) {
return nil;
}
NSTableCellView* result = [tableView makeViewWithIdentifier:@"MainCell" owner:tableView];
NSTextField* displayName = [result viewWithTag:DISPLAYNAME_TAG];
NSTextField* displayRingID = [result viewWithTag:RING_ID_LABEL];
NSImageView* photoView = [result viewWithTag:IMAGE_TAG];
NSView* presenceView = [result viewWithTag:PRESENCE_TAG];
[displayName setStringValue:@""];
[displayRingID setStringValue:@""];
[photoView setHidden: YES];
[presenceView setHidden:YES];
// setup conference cell
if(conversations.size() > 1) {
NSString* displayNameString = @"";
for (auto conversation : conversations) {
auto accountID = conversation.accountId;
auto convID = conversation.convId;
auto *convMod = convModel->owner.accountModel->getAccountInfo(accountID).conversationModel.get();
auto *conversationInfo = &(*getConversationFromUid(convID, *convMod, false));
if (displayNameString.length > 0) {
displayNameString = [displayNameString stringByAppendingString:@", "];
}
displayNameString = [displayNameString stringByAppendingString: bestNameForConversation(*conversationInfo, *convMod)];
}
[displayName setStringValue:displayNameString];
[NSLayoutConstraint deactivateConstraints:[photoView constraints]];
NSArray* constraints = [NSLayoutConstraint
constraintsWithVisualFormat:@"H:[photoView(0)]"
options:0
metrics:nil views:NSDictionaryOfVariableBindings(photoView)];
[NSLayoutConstraint activateConstraints:constraints];
return result;
}
lrc::api::AccountConversation conversation = conversations.front();
auto accountID = conversation.accountId;
auto convID = conversation.convId;
auto *convMod = convModel->owner.accountModel->getAccountInfo(accountID).conversationModel.get();
auto *conversationInfo = &(*getConversationFromUid(convID, *convMod, false));
if (conversationInfo->participants.empty()) {
return nil;
}
NSString* displayNameString = bestNameForConversation(*conversationInfo, *convMod);
NSString* displayIDString = bestIDForConversation(*conversationInfo, *convMod);
if(displayNameString.length == 0 || [displayNameString isEqualToString:displayIDString]) {
[displayName setStringValue:displayIDString];
[displayRingID setHidden:YES];
} else {
[displayName setStringValue:displayNameString];
[displayRingID setStringValue:displayIDString];
[displayRingID setHidden:NO];
}
auto& imageManip = reinterpret_cast<Interfaces::ImageManipulationDelegate&>(GlobalInstances::pixmapManipulator());
NSImage* image = QtMac::toNSImage(qvariant_cast<QPixmap>(imageManip.conversationPhoto(*conversationInfo, convMod->owner)));
if(image) {
[NSLayoutConstraint deactivateConstraints:[photoView constraints]];
NSArray* constraints = [NSLayoutConstraint
constraintsWithVisualFormat:@"H:[photoView(54)]"
options:0
metrics:nil views:NSDictionaryOfVariableBindings(photoView)];
[NSLayoutConstraint activateConstraints:constraints];
} else {
[NSLayoutConstraint deactivateConstraints:[photoView constraints]];
NSArray* constraints = [NSLayoutConstraint
constraintsWithVisualFormat:@"H:[photoView(0)]"
options:0
metrics:nil views:NSDictionaryOfVariableBindings(photoView)];
[NSLayoutConstraint activateConstraints:constraints];
}
[photoView setHidden: NO];
[photoView setImage: image];
try {
auto contact = convModel->owner.contactModel->getContact(conversationInfo->participants[0]);
if (contact.isPresent) {
[presenceView setHidden:NO];
}
} catch (std::out_of_range& e) {
NSLog(@"viewForTableColumn: getContact - out of range");
}
return result;
}
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
return 60.0;
}
#pragma mark - NSTableDataSource methods
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
if(!convModel) {
return 0;
}
if (tableView == contactsView) {
return values.count(lrc::api::ConferenceableItem::CONTACT) ? values.value(lrc::api::ConferenceableItem::CONTACT).size() : 0;
} else if (tableView == callsView) {
return values.count(lrc::api::ConferenceableItem::CALL) ? values.value(lrc::api::ConferenceableItem::CALL).size() : 0;
}
return 0;
}
@end