blob: 870be2c20c223f6f58b39ed4eace38e4baa227c0 [file] [log] [blame]
Alexandre Lision3b0bd332015-03-15 18:43:07 -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.
Alexandre Lision3b0bd332015-03-15 18:43:07 -040018 */
19
20#import "PersonsVC.h"
21
Alexandre Lision2db8f472015-07-22 15:05:46 -040022
23//Qt
Alexandre Lision3b0bd332015-03-15 18:43:07 -040024#import <QSortFilterProxyModel>
Alexandre Lision3b0bd332015-03-15 18:43:07 -040025#import <QtMacExtras/qmacfunctions.h>
26#import <QPixmap>
27
Alexandre Lision2db8f472015-07-22 15:05:46 -040028//LRC
29#import <person.h>
30#import <personmodel.h>
31#import <callmodel.h>
32#import <contactmethod.h>
33#import <categorizedcontactmodel.h>
Alexandre Lision7a166e42015-09-02 15:04:43 -040034#import <globalinstances.h>
Alexandre Lision2db8f472015-07-22 15:05:46 -040035
Alexandre Lision3b0bd332015-03-15 18:43:07 -040036#import "backends/AddressBookBackend.h"
37#import "QNSTreeController.h"
38#import "delegates/ImageManipulationDelegate.h"
Alexandre Lision4e280d62015-09-09 15:56:30 -040039#import "views/HoverTableRowView.h"
Alexandre Lision6da08a82015-09-24 17:09:24 -040040#import "views/ContextualTableCellView.h"
Alexandre Lision3b0bd332015-03-15 18:43:07 -040041
42class ReachablePersonModel : public QSortFilterProxyModel
43{
44public:
45 ReachablePersonModel(QAbstractItemModel* parent) : QSortFilterProxyModel(parent)
46 {
47 setSourceModel(parent);
48 }
49 virtual bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
50 {
51 return sourceModel()->index(source_row,0,source_parent).flags() & Qt::ItemIsEnabled;
52 }
53};
54
55
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040056@interface PersonsVC () {
Alexandre Lision3b0bd332015-03-15 18:43:07 -040057
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040058 QNSTreeController *treeController;
59 __unsafe_unretained IBOutlet NSOutlineView *personsView;
60 QSortFilterProxyModel *contactProxyModel;
61
62}
Alexandre Lision3b0bd332015-03-15 18:43:07 -040063
64@end
65
66@implementation PersonsVC
Alexandre Lision4dfcafc2015-08-20 12:43:23 -040067
68// Tags for views
69NSInteger const IMAGE_TAG = 100;
70NSInteger const DISPLAYNAME_TAG = 200;
71NSInteger const DETAILS_TAG = 300;
72NSInteger const CALL_BUTTON_TAG = 400;
Alexandre Lision3b0bd332015-03-15 18:43:07 -040073
74-(void) awakeFromNib
75{
Alexandre Lision3b0bd332015-03-15 18:43:07 -040076 NSLog(@"INIT PersonsVC");
77 contactProxyModel = new ReachablePersonModel(CategorizedContactModel::instance());
78 contactProxyModel->setSortRole(static_cast<int>(Qt::DisplayRole));
79 contactProxyModel->sort(0,Qt::AscendingOrder);
80 treeController = [[QNSTreeController alloc] initWithQModel:contactProxyModel];
81
82 [treeController setAvoidsEmptySelection:NO];
83 [treeController setChildrenKeyPath:@"children"];
84
85 [personsView bind:@"content" toObject:treeController withKeyPath:@"arrangedObjects" options:nil];
86 [personsView bind:@"sortDescriptors" toObject:treeController withKeyPath:@"sortDescriptors" options:nil];
87 [personsView bind:@"selectionIndexPaths" toObject:treeController withKeyPath:@"selectionIndexPaths" options:nil];
88 [personsView setTarget:self];
89 [personsView setDoubleAction:@selector(callContact:)];
90
91 CategorizedContactModel::instance()->setUnreachableHidden(YES);
Alexandre Lision3b0bd332015-03-15 18:43:07 -040092}
93
Alexandre Lision54b0fae2015-08-04 15:19:01 -040094- (void) dealloc
95{
96 delete contactProxyModel;
97}
98
Alexandre Lision3b0bd332015-03-15 18:43:07 -040099- (IBAction)callContact:(id)sender
100{
101 if([[treeController selectedNodes] count] > 0) {
102 QModelIndex qIdx = [treeController toQIdx:[treeController selectedNodes][0]];
103 ContactMethod* m = nil;
104 if(((NSTreeNode*)[treeController selectedNodes][0]).indexPath.length == 2) {
105 // Person
106 QVariant var = qIdx.data((int)Person::Role::Object);
107 if (var.isValid()) {
108 Person *c = var.value<Person*>();
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400109 if (c->phoneNumbers().size() > 0) {
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400110 m = c->phoneNumbers().first();
111 }
112 }
113 } else if (((NSTreeNode*)[treeController selectedNodes][0]).indexPath.length == 3) {
114 //ContactMethod
115 QVariant var = qIdx.data(static_cast<int>(ContactMethod::Role::Object));
116 if (var.isValid()) {
117 m = var.value<ContactMethod *>();
118 }
119 }
120
121 if(m){
122 Call* c = CallModel::instance()->dialingCall();
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400123 c->setPeerContactMethod(m);
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400124 c << Call::Action::ACCEPT;
125 }
126 }
127}
128
129#pragma mark - NSOutlineViewDelegate methods
130
131// -------------------------------------------------------------------------------
132// shouldSelectItem:item
133// -------------------------------------------------------------------------------
134- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item;
135{
136 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
137 if(!qIdx.isValid())
138 return NO;
139
140 if(!qIdx.parent().isValid()) {
141 return NO;
142 } else {
143 return YES;
144 }
145}
146
147// -------------------------------------------------------------------------------
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400148// shouldEditTableColumn:tableColumn:item
149//
150// Decide to allow the edit of the given outline view "item".
151// -------------------------------------------------------------------------------
152- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
153{
154 return NO;
155}
156
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400157/* View Based OutlineView: See the delegate method -tableView:viewForTableColumn:row: in NSTableView.
158 */
159- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400160{
161 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400162
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400163 NSTableCellView *result;
164
165 if(!qIdx.parent().isValid()) {
166 result = [outlineView makeViewWithIdentifier:@"LetterCell" owner:outlineView];
167 [result setWantsLayer:YES];
168 [result setLayer:[CALayer layer]];
169 [result.layer setBackgroundColor:[NSColor selectedControlColor].CGColor];
170 } else if(((NSTreeNode*)item).indexPath.length == 2) {
Alexandre Lision6da08a82015-09-24 17:09:24 -0400171 result = [outlineView makeViewWithIdentifier:@"PersonCell" owner:outlineView];
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400172 NSImageView* photoView = [result viewWithTag:IMAGE_TAG];
173 Person* p = qvariant_cast<Person*>(qIdx.data((int)Person::Role::Object));
174
Alexandre Lisionde0314b2015-09-02 15:45:21 -0400175 QVariant photo = GlobalInstances::pixmapManipulator().contactPhoto(p, QSize(40,40));
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400176 [photoView setImage:QtMac::toNSImage(qvariant_cast<QPixmap>(photo))];
Alexandre Lision6da08a82015-09-24 17:09:24 -0400177 [((ContextualTableCellView*) result) setContextualsControls:[NSMutableArray arrayWithObject:[result viewWithTag:CALL_BUTTON_TAG]]];
178
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400179 NSTextField* details = [result viewWithTag:DETAILS_TAG];
180 if (p && p->phoneNumbers().size() > 0)
181 [details setStringValue:p->phoneNumbers().first()->uri().toNSString()];
182 } else {
183 result = [outlineView makeViewWithIdentifier:@"ContactMethodCell" owner:outlineView];
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400184 }
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400185
186 NSTextField* displayName = [result viewWithTag:DISPLAYNAME_TAG];
187 [displayName setStringValue:qIdx.data(Qt::DisplayRole).toString().toNSString()];
188
189 return result;
190}
191
Alexandre Lision4e280d62015-09-09 15:56:30 -0400192/* View Based OutlineView: See the delegate method -tableView:rowViewForRow: in NSTableView.
193 */
194- (NSTableRowView *)outlineView:(NSOutlineView *)outlineView rowViewForItem:(id)item
195{
196 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
Alexandre Lision4e280d62015-09-09 15:56:30 -0400197 HoverTableRowView* result = [outlineView makeViewWithIdentifier:@"HoverRowView" owner:nil];
198 if(!qIdx.parent().isValid()) {
199 [result setHighlightable:NO];
200 } else
201 [result setHighlightable:YES];
202
203 return result;
204}
205
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400206- (IBAction)callClickedAtRow:(id)sender {
207 NSInteger row = [personsView rowForView:sender];
208 [personsView selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
209 [self callContact:nil];
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400210}
211
212// -------------------------------------------------------------------------------
213// outlineViewSelectionDidChange:notification
214// -------------------------------------------------------------------------------
215- (void)outlineViewSelectionDidChange:(NSNotification *)notification
216{
217
218}
219
220- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
221{
222 QModelIndex qIdx = [treeController toQIdx:((NSTreeNode*)item)];
Alexandre Lision4dfcafc2015-08-20 12:43:23 -0400223 return (((NSTreeNode*)item).indexPath.length == 2) ? 60.0 : 20.0;
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400224}
225
Alexandre Lision3b0bd332015-03-15 18:43:07 -0400226@end