1/* Tools.m 2 * 3 * Copyright (C) 2004-2016 Free Software Foundation, Inc. 4 * 5 * Author: Enrico Sersale <enrico@imago.ro> 6 * Date: January 2004 7 * 8 * This file is part of the GNUstep GWorkspace application 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. 23 */ 24 25#import <Foundation/Foundation.h> 26#import <AppKit/AppKit.h> 27#include <math.h> 28#import "Tools.h" 29#import "Inspector.h" 30#import "IconView.h" 31#import "Functions.h" 32#import "FSNodeRep.h" 33 34#define ICNSIZE 48 35 36static NSString *nibName = @"Tools"; 37 38@implementation Tools 39 40- (void)dealloc 41{ 42 RELEASE (toolsBox); 43 RELEASE (errLabel); 44 RELEASE (mainBox); 45 RELEASE (insppaths); 46 RELEASE (extensions); 47 RELEASE (currentApp); 48 49 [super dealloc]; 50} 51 52- (id)initForInspector:(id)insp 53{ 54 self = [super init]; 55 56 if (self) { 57 NSRect r; 58 id cell; 59 60 if ([NSBundle loadNibNamed: nibName owner: self] == NO) { 61 NSLog(@"failed to load %@!", nibName); 62 DESTROY (self); 63 return self; 64 } 65 66 RETAIN (mainBox); 67 RETAIN (toolsBox); 68 RELEASE (win); 69 70 inspector = insp; 71 [iconView setInspector: inspector]; 72 ws = [NSWorkspace sharedWorkspace]; 73 74 [scrollView setBorderType: NSBezelBorder]; 75 [scrollView setHasHorizontalScroller: YES]; 76 [scrollView setHasVerticalScroller: NO]; 77 78 cell = [NSButtonCell new]; 79 [cell setButtonType: NSPushOnPushOffButton]; 80 [cell setImagePosition: NSImageOnly]; 81 82 matrix = [[NSMatrix alloc] initWithFrame: NSZeroRect 83 mode: NSRadioModeMatrix prototype: cell 84 numberOfRows: 0 numberOfColumns: 0]; 85 RELEASE (cell); 86 [matrix setIntercellSpacing: NSZeroSize]; 87 [matrix setCellSize: NSMakeSize(64, [[scrollView contentView] bounds].size.height)]; 88 [matrix setAllowsEmptySelection: YES]; 89 [matrix setTarget: self]; 90 [matrix setAction: @selector(setCurrentApplication:)]; 91 [matrix setDoubleAction: @selector(openFile:)]; 92 [scrollView setDocumentView: matrix]; 93 RELEASE (matrix); 94 95 r = [toolsBox bounds]; 96 r.origin.y = 165; 97 r.size.height = 25; 98 errLabel = [[NSTextField alloc] initWithFrame: r]; 99 [errLabel setAlignment: NSCenterTextAlignment]; 100 [errLabel setFont: [NSFont systemFontOfSize: 18]]; 101 [errLabel setBackgroundColor: [NSColor windowBackgroundColor]]; 102 [errLabel setTextColor: [NSColor darkGrayColor]]; 103 [errLabel setBezeled: NO]; 104 [errLabel setEditable: NO]; 105 [errLabel setSelectable: NO]; 106 [errLabel setStringValue: NSLocalizedString(@"No Tools Inspector", @"")]; 107 108 insppaths = nil; 109 currentApp = nil; 110 extensions = nil; 111 valid = YES; 112 [okButt setEnabled: NO]; 113 } 114 115 return self; 116} 117 118- (NSView *)inspView 119{ 120 return mainBox; 121} 122 123- (NSString *)winname 124{ 125 return NSLocalizedString(@"Tools Inspector", @""); 126} 127 128- (void)activateForPaths:(NSArray *)paths 129{ 130 BOOL toolsok = YES; 131 NSInteger pathscount; 132 NSInteger i; 133 134 if (paths == nil) { 135 DESTROY (insppaths); 136 return; 137 } 138 139 [okButt setEnabled: NO]; 140 141 pathscount = [paths count]; 142 143 if (pathscount == 1) 144 { 145 FSNode *node = [FSNode nodeWithPath: [paths objectAtIndex: 0]]; 146 NSImage *icon = [[FSNodeRep sharedInstance] iconOfSize: ICNSIZE forNode: node]; 147 148 [iconView setImage: icon]; 149 [titleField setStringValue: [node name]]; 150 } 151 else 152 { 153 NSImage *icon = [[FSNodeRep sharedInstance] multipleSelectionIconOfSize: ICNSIZE]; 154 NSString *items = NSLocalizedString(@"items", @""); 155 items = [NSString stringWithFormat: @"%li %@", (long int)pathscount, items]; 156 [titleField setStringValue: items]; 157 [iconView setImage: icon]; 158 } 159 160 for (i = 0; i < [paths count]; i++) 161 { 162 FSNode *node = [FSNode nodeWithPath: [paths objectAtIndex: i]]; 163 164 if ([node isValid]) 165 { 166 if ([node isPlain] == NO) 167 { 168 toolsok = NO; 169 break; 170 } 171 } 172 else 173 { 174 toolsok = NO; 175 break; 176 } 177 } 178 179 if (toolsok == YES) 180 { 181 if (valid == NO) 182 { 183 [errLabel removeFromSuperview]; 184 [mainBox addSubview: toolsBox]; 185 valid = YES; 186 } 187 [self findApplicationsForPaths: paths]; 188 189 } 190 else 191 { 192 if (valid == YES) 193 { 194 [toolsBox removeFromSuperview]; 195 [mainBox addSubview: errLabel]; 196 valid = NO; 197 } 198 } 199} 200 201- (void)findApplicationsForPaths:(NSArray *)paths 202{ 203 NSMutableDictionary *extensionsAndApps; 204 NSMutableArray *commonApps; 205 NSString *s; 206 id cell; 207 BOOL appsforext; 208 NSInteger i, count; 209 210 ASSIGN (insppaths, paths); 211 212 RELEASE (extensions); 213 extensions = [NSMutableArray new]; 214 extensionsAndApps = [NSMutableDictionary dictionary]; 215 216 DESTROY (currentApp); 217 [defAppField setStringValue: @""]; 218 [defPathField setStringValue: @""]; 219 220 appsforext = YES; 221 222 for (i = 0; i < [insppaths count]; i++) 223 { 224 NSString *ext = [[insppaths objectAtIndex: i] pathExtension]; 225 226 if ([extensions containsObject: ext] == NO) 227 { 228 NSDictionary *extinfo = [ws infoForExtension: ext]; 229 230 if (extinfo) 231 { 232 NSMutableArray *appsnames = [NSMutableArray arrayWithCapacity: 1]; 233 [appsnames addObjectsFromArray: [extinfo allKeys]]; 234 [extensionsAndApps setObject: appsnames forKey: ext]; 235 [extensions addObject: ext]; 236 } 237 else 238 { 239 appsforext = NO; 240 } 241 } 242 } 243 244 if ([extensions count] == 1) { 245 NSString *ext = [extensions objectAtIndex: 0]; 246 commonApps = [NSMutableArray arrayWithArray: [extensionsAndApps objectForKey: ext]]; 247 currentApp = [ws getBestAppInRole: nil forExtension: ext]; 248 RETAIN (currentApp); 249 250 } 251 else 252 { 253 NSInteger j, n; 254 255 for (i = 0; i < [extensions count]; i++) 256 { 257 NSString *ext1 = [extensions objectAtIndex: i]; 258 NSMutableArray *a1 = [extensionsAndApps objectForKey: ext1]; 259 260 for (j = 0; j < [extensions count]; j++) { 261 NSString *ext2 = [extensions objectAtIndex: j]; 262 NSMutableArray *a2 = [extensionsAndApps objectForKey: ext2]; 263 264 count = [a1 count]; 265 for (n = 0; n < count; n++) { 266 NSString *s = [a1 objectAtIndex: n]; 267 if ([a2 containsObject: s] == NO) { 268 [a1 removeObject: s]; 269 count--; 270 n--; 271 } 272 } 273 [extensionsAndApps setObject: a1 forKey: ext1]; 274 } 275 } 276 277 commonApps = [NSMutableArray array]; 278 279 for (i = 0; i < [extensions count]; i++) { 280 NSString *ext = [extensions objectAtIndex: i]; 281 NSArray *apps = [extensionsAndApps objectForKey: ext]; 282 283 for (j = 0; j < [apps count]; j++) { 284 NSString *app = [apps objectAtIndex: j]; 285 if ([commonApps containsObject: app] == NO) { 286 [commonApps addObject: app]; 287 } 288 } 289 } 290 291 if ([commonApps count] != 0) { 292 BOOL iscommapp = YES; 293 NSString *ext1 = [extensions objectAtIndex: 0]; 294 295 currentApp = [ws getBestAppInRole: nil forExtension: ext1]; 296 297 if ([commonApps containsObject: currentApp]) { 298 for (i = 1; i < [extensions count]; i++) { 299 NSString *ext2 = [extensions objectAtIndex: i]; 300 NSString *app = [ws getBestAppInRole: nil forExtension: ext2]; 301 302 if ([currentApp isEqual: app] == NO) { 303 iscommapp = NO; 304 } 305 } 306 } else { 307 currentApp = nil; 308 } 309 310 if ((iscommapp == YES) && (currentApp != nil) && appsforext) { 311 RETAIN (currentApp); 312 } else { 313 currentApp = nil; 314 } 315 } 316 } 317 318 if (([commonApps count] != 0) && (currentApp != nil) && (appsforext == YES)) { 319 [okButt setEnabled: YES]; 320 } else { 321 [okButt setEnabled: NO]; 322 } 323 324 count = [commonApps count]; 325 326 [matrix renewRows: 1 columns: count]; 327 [matrix sizeToCells]; 328 329 if (appsforext) { 330 for (i = 0; i < count; i++) { 331 NSString *appName = [commonApps objectAtIndex: i]; 332 FSNode *node = [FSNode nodeWithPath: [ws fullPathForApplication: appName]]; 333 NSImage *icon = [[FSNodeRep sharedInstance] iconOfSize: ICNSIZE forNode: node]; 334 335 cell = [matrix cellAtRow: 0 column: i]; 336 [cell setImage: icon]; 337 [cell setTitle: appName]; 338 } 339 340 [matrix sizeToCells]; 341 } 342 343 if (currentApp != nil) { 344 NSArray *cells = [matrix cells]; 345 346 for(i = 0; i < [cells count]; i++) { 347 cell = [cells objectAtIndex: i]; 348 if(cell && ([[cell title] isEqualToString: currentApp])) { 349 [matrix selectCellAtRow: 0 column: i]; 350 [matrix scrollCellToVisibleAtRow: 0 column: i]; 351 break; 352 } 353 } 354 355 [defAppField setStringValue: [currentApp stringByDeletingPathExtension]]; 356 s = [ws fullPathForApplication: currentApp]; 357 if (s != nil) { 358 s = relativePathFit(defPathField, s); 359 } else { 360 s = @""; 361 } 362 [defPathField setStringValue: s]; 363 } 364} 365 366- (void)setCurrentApplication:(id)sender 367{ 368 NSString *s; 369 370 ASSIGN (currentApp, [[sender selectedCell] title]); 371 s = [ws fullPathForApplication: currentApp]; 372 s = relativePathFit(defPathField, s); 373 [defPathField setStringValue: s]; 374 [defAppField setStringValue: [currentApp stringByDeletingPathExtension]]; 375} 376 377- (IBAction)setDefaultApplication:(id)sender 378{ 379 NSString *ext, *app; 380 NSDictionary *changedInfo; 381 NSArray *cells; 382 NSMutableArray *newApps; 383 id cell; 384 FSNode *node; 385 NSImage *icon; 386 NSInteger i, count; 387 388 for (i = 0; i < [extensions count]; i++) 389 { 390 ext = [extensions objectAtIndex: i]; 391 [ws setBestApp: currentApp inRole: nil forExtension: ext]; 392 } 393 394 changedInfo = [NSDictionary dictionaryWithObjectsAndKeys: 395 currentApp, @"app", 396 extensions, @"exts", nil]; 397 398 [[NSDistributedNotificationCenter defaultCenter] 399 postNotificationName: @"GWAppForExtensionDidChangeNotification" 400 object: nil 401 userInfo: changedInfo]; 402 403 newApps = [NSMutableArray arrayWithCapacity: 1]; 404 [newApps addObject: currentApp]; 405 406 cells = [matrix cells]; 407 for(i = 0; i < [cells count]; i++) 408 { 409 app = [[cells objectAtIndex: i] title]; 410 if ([app isEqual: currentApp] == NO) 411 { 412 [newApps insertObject: app atIndex: [newApps count]]; 413 } 414 } 415 416 count = [newApps count]; 417 [matrix renewRows: 1 columns: count]; 418 419 for (i = 0; i < count; i++) 420 { 421 cell = [matrix cellAtRow: 0 column: i]; 422 app = [newApps objectAtIndex: i]; 423 [cell setTitle: app]; 424 node = [FSNode nodeWithPath: [ws fullPathForApplication: app]]; 425 icon = [[FSNodeRep sharedInstance] iconOfSize: ICNSIZE forNode: node]; 426 [cell setImage: icon]; 427 } 428 429 [matrix scrollCellToVisibleAtRow: 0 column: 0]; 430 [matrix selectCellAtRow: 0 column: 0]; 431} 432 433- (void)openFile:(id)sender 434{ 435 NSInteger i; 436 437 for (i = 0; i < [insppaths count]; i++) 438 { 439 NSString *fpath = [insppaths objectAtIndex: i]; 440 441 NS_DURING 442 { 443 [ws openFile: fpath withApplication: [[sender selectedCell] title]]; 444 } 445 NS_HANDLER 446 { 447 NSRunAlertPanel(NSLocalizedString(@"error", @""), 448 [NSString stringWithFormat: @"%@ %@!", 449 NSLocalizedString(@"Can't open ", @""), [fpath lastPathComponent]], 450 NSLocalizedString(@"OK", @""), 451 nil, 452 nil); 453 } 454 NS_ENDHANDLER 455 } 456} 457 458- (void)watchedPathDidChange:(NSDictionary *)info 459{ 460} 461 462@end 463