blob: e75ef3adb77981260f181b53ac5ba5bdc7737ea2 [file] [log] [blame]
Alexandre Lision74dd47f2015-04-14 13:47:42 -04001/*
2 * Copyright (C) 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
31#import "CallView.h"
32
33#import <QItemSelectionModel>
34#import <QAbstractProxyModel>
35#import <QUrl>
36
37#import <video/configurationproxy.h>
38#import <video/sourcemodel.h>
39#import <video/previewmanager.h>
40#import <video/renderer.h>
41#import <video/device.h>
42#import <video/devicemodel.h>
43
44@interface CallView ()
45
46@property NSMenu *contextualMenu;
47
48@end
49
50@implementation CallView
51@synthesize contextualMenu;
52@synthesize shouldAcceptInteractions;
53
54
55- (id)initWithFrame:(NSRect)frame
56{
57 self = [super initWithFrame:frame];
58 if (self)
59 {
60 [self registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, nil]];
61 }
Alexandre Lisiona1eee3c2015-08-10 13:44:51 -040062
63 [self.window setAcceptsMouseMovedEvents:YES];
64
65 NSTrackingAreaOptions options = (NSTrackingActiveAlways | NSTrackingInVisibleRect | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved);
66
67 NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:frame
68 options:options
69 owner:self
70 userInfo:nil];
71
72 [self addTrackingArea:area];
Alexandre Lision74dd47f2015-04-14 13:47:42 -040073 return self;
74}
75
76
77#pragma mark - Destination Operations
78
79- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
80{
81 /*------------------------------------------------------
82 method called whenever a drag enters our drop zone
83 --------------------------------------------------------*/
84 NSLog(@"Dragging entered");
85
86 NSURL* fileURL = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
Alexandre Lision81c97212015-06-17 15:51:53 -040087 CFStringRef fileExtension = (__bridge CFStringRef) [fileURL.path pathExtension];
Alexandre Lision74dd47f2015-04-14 13:47:42 -040088 CFStringRef fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);
89
90 // Check if the pasteboard contains image data and source/user wants it copied
91 if ( [sender draggingSourceOperationMask] & NSDragOperationCopy &&
92 (UTTypeConformsTo(fileUTI, kUTTypeVideo)) || (UTTypeConformsTo(fileUTI, kUTTypeMovie))) {
93
94 //highlight our drop zone
95 highlight=YES;
96
97 [self setNeedsDisplay: YES];
98
99 /* When an image from one window is dragged over another, we want to resize the dragging item to
100 * preview the size of the image as it would appear if the user dropped it in. */
101 [sender enumerateDraggingItemsWithOptions:NSDraggingItemEnumerationConcurrent
102 forView:self
103 classes:[NSArray arrayWithObject:[NSPasteboardItem class]]
104 searchOptions:nil
105 usingBlock:^(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop) {
106 *stop = YES;
107 }];
Alexandre Lision81c97212015-06-17 15:51:53 -0400108 CFRelease(fileUTI);
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400109 //accept data as a copy operation
110 return NSDragOperationCopy;
111 }
112
Alexandre Lision81c97212015-06-17 15:51:53 -0400113 CFRelease(fileUTI);
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400114 return NSDragOperationNone;
115}
116
117- (void)draggingExited:(id <NSDraggingInfo>)sender
118{
119 /*------------------------------------------------------
120 method called whenever a drag exits our drop zone
121 --------------------------------------------------------*/
122 //remove highlight of the drop zone
123 highlight=NO;
124
125 [self setNeedsDisplay: YES];
126}
127
128-(void)drawRect:(NSRect)rect
129{
130 /*------------------------------------------------------
131 draw method is overridden to do drop highlighing
132 --------------------------------------------------------*/
133 //do the usual draw operation to display the image
134 [super drawRect:rect];
135
136 if ( highlight ) {
137 //highlight by overlaying a gray border
138 [[NSColor blueColor] set];
139 [NSBezierPath setDefaultLineWidth: 5];
140 [NSBezierPath strokeRect: rect];
141 }
142}
143
144- (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
145{
146 /*------------------------------------------------------
147 method to determine if we can accept the drop
148 --------------------------------------------------------*/
149 //finished with the drag so remove any highlighting
150 highlight=NO;
151
152 [self setNeedsDisplay: YES];
153
154 NSURL* fileURL = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
Alexandre Lision81c97212015-06-17 15:51:53 -0400155 CFStringRef fileExtension = (__bridge CFStringRef) [fileURL.path pathExtension];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400156 CFStringRef fileUTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, fileExtension, NULL);
157
Alexandre Lision81c97212015-06-17 15:51:53 -0400158 BOOL conforms = (UTTypeConformsTo(fileUTI, kUTTypeVideo)) || (UTTypeConformsTo(fileUTI, kUTTypeMovie));
159 CFRelease(fileUTI);
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400160 //check to see if we can accept the data
Alexandre Lision81c97212015-06-17 15:51:53 -0400161 return conforms;
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400162}
163
164- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
165{
166 /*------------------------------------------------------
167 method that should handle the drop data
168 --------------------------------------------------------*/
169 if ( [sender draggingSource] != self ) {
170 NSURL* fileURL = [NSURL URLFromPasteboard: [sender draggingPasteboard]];
171 Video::SourceModel::instance()->setFile(QUrl::fromLocalFile(QString::fromUtf8([fileURL.path UTF8String])));
172 }
173
174 return YES;
175}
176
177- (void)showContextualMenu:(NSEvent *)theEvent {
178
179 contextualMenu = [[NSMenu alloc] initWithTitle:@"Switch camera"];
180
181 for(int i = 0 ; i < Video::DeviceModel::instance()->devices().size() ; ++i) {
182 Video::Device* device = Video::DeviceModel::instance()->devices()[i];
183 [contextualMenu insertItemWithTitle:device->name().toNSString() action:@selector(switchInput:) keyEquivalent:@"" atIndex:i];
184 }
185
186 [contextualMenu addItem:[NSMenuItem separatorItem]];
187 [contextualMenu insertItemWithTitle:@"Choose file" action:@selector(chooseFile:) keyEquivalent:@"" atIndex:contextualMenu.itemArray.count];
188
189 [NSMenu popUpContextMenu:contextualMenu withEvent:theEvent forView:self];
190}
191
Alexandre Lisiona1eee3c2015-08-10 13:44:51 -0400192- (void)mouseMoved:(NSEvent *)theEvent
193{
194 [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel showContextualMenu
195 [self performSelector:@selector(mouseIdle:) withObject:theEvent afterDelay:3];
196 if (self.callDelegate)
197 [self.callDelegate mouseIsMoving:YES];
198}
199
200- (void) mouseIdle:(NSEvent *)theEvent
201{
202 if (self.callDelegate && shouldAcceptInteractions)
203 [self.callDelegate mouseIsMoving:NO];
204}
205
206
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400207- (void)mouseUp:(NSEvent *)theEvent
208{
209 if([theEvent clickCount] == 1 && shouldAcceptInteractions) {
210 if(!contextualMenu)
211 [self performSelector:@selector(showContextualMenu:) withObject:theEvent afterDelay:[NSEvent doubleClickInterval]];
212 else
213 contextualMenu = nil;
214 }
215 else if([theEvent clickCount] == 2)
216 {
217 [NSObject cancelPreviousPerformRequestsWithTarget:self]; // cancel showContextualMenu
Alexandre Lisiona1eee3c2015-08-10 13:44:51 -0400218 if(self.callDelegate)
219 [self.callDelegate callShouldToggleFullScreen];
Alexandre Lision74dd47f2015-04-14 13:47:42 -0400220 }
221}
222
223- (void) switchInput:(NSMenuItem*) sender
224{
225 int index = [contextualMenu indexOfItem:sender];
226 Video::SourceModel::instance()->switchTo(Video::DeviceModel::instance()->devices()[index]);
227}
228
229- (void) chooseFile:(NSMenuItem*) sender
230{
231 NSOpenPanel *browsePanel = [[NSOpenPanel alloc] init];
232 [browsePanel setDirectoryURL:[NSURL URLWithString:NSHomeDirectory()]];
233 [browsePanel setCanChooseFiles:YES];
234 [browsePanel setCanChooseDirectories:NO];
235 [browsePanel setCanCreateDirectories:NO];
236
237 //NSMutableArray* fileTypes = [[NSMutableArray alloc] initWithArray:[NSImage imageTypes]];
238 NSMutableArray* fileTypes = [NSMutableArray array];
239 [fileTypes addObject:(__bridge NSString *)kUTTypeVideo];
240 [fileTypes addObject:(__bridge NSString *)kUTTypeMovie];
241 [browsePanel setAllowedFileTypes:fileTypes];
242
243 [browsePanel beginSheetModalForWindow:[self window] completionHandler:^(NSInteger result) {
244 if (result == NSFileHandlingPanelOKButton) {
245 NSURL* theDoc = [[browsePanel URLs] objectAtIndex:0];
246 Video::SourceModel::instance()->setFile(QUrl::fromLocalFile(QString::fromUtf8([theDoc.path UTF8String])));
247 }
248 }];
249
250}
251
252@end