Skip to content
Browse files

Rewrite how profiles menus are maintained to apply diffs of rebuildin…

…g from scratch. Fixes bug 907.

git-svn-id: http://iterm2.googlecode.com/svn/trunk@854 5c829b59-20ba-c297-566c-b9ce016b2d6a
  • Loading branch information...
1 parent 6ea65a5 commit 638e0913a6b4102497bf437e5fd4e6dc3db64bf2 @gnachman gnachman committed May 25, 2011
View
284 BookmarkModel.m
@@ -25,13 +25,20 @@
#import <iTerm/ITAddressBookMgr.h>
#import <iTerm/BookmarkModel.h>
+id gAltOpenAllRepresentedObject;
@implementation BookmarkModel
++ (void)initialize
+{
+ gAltOpenAllRepresentedObject = [[NSObject alloc] init];
+}
+
- (BookmarkModel*)init
{
bookmarks_ = [[NSMutableArray alloc] init];
defaultBookmarkGuid_ = @"";
+ journal_ = [[NSMutableArray alloc] init];
return self;
}
@@ -62,6 +69,7 @@ + (BookmarkModel*)sessionsInstance
- (void)dealloc
{
[super dealloc];
+ [journal_ release];
NSLog(@"Deallocating bookmark model!");
}
@@ -236,6 +244,10 @@ - (void)addBookmark:(Bookmark*)bookmark inSortedOrder:(BOOL)sort
[bookmarks_ addObject:[NSDictionary dictionaryWithDictionary:bookmark]];
}
NSString* isDeprecatedDefaultBookmark = [bookmark objectForKey:KEY_DEFAULT_BOOKMARK];
+
+ // The call to setDefaultByGuid may add a journal entry so make sure this one comes first.
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_ADD bookmark:bookmark model:self]];
+
if (![self defaultBookmark] || (isDeprecatedDefaultBookmark && [isDeprecatedDefaultBookmark isEqualToString:@"Yes"])) {
[self setDefaultByGuid:[bookmark objectForKey:KEY_GUID]];
}
@@ -270,7 +282,8 @@ - (void)removeBookmarksAtIndices:(NSArray*)indices
for (int j = [sorted count] - 1; j >= 0; j--) {
int i = [[sorted objectAtIndex:j] intValue];
assert(i >= 0);
-
+
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_REMOVE bookmark:[bookmarks_ objectAtIndex:i] model:self]];
[bookmarks_ removeObjectAtIndex:i];
if (![self defaultBookmark] && [bookmarks_ count]) {
[self setDefaultByGuid:[[bookmarks_ objectAtIndex:0] objectForKey:KEY_GUID]];
@@ -282,6 +295,7 @@ - (void)removeBookmarksAtIndices:(NSArray*)indices
- (void)removeBookmarkAtIndex:(int)i
{
assert(i >= 0);
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_REMOVE bookmark:[bookmarks_ objectAtIndex:i] model:self]];
[bookmarks_ removeObjectAtIndex:i];
if (![self defaultBookmark] && [bookmarks_ count]) {
[self setDefaultByGuid:[[bookmarks_ objectAtIndex:0] objectForKey:KEY_GUID]];
@@ -302,14 +316,36 @@ - (void)removeBookmarkWithGuid:(NSString*)guid
}
}
+// A change in bookmarks is journal-worthy only if the name, shortcut, tags, or guid changes.
+- (BOOL)bookmark:(Bookmark*)a differsJournalablyFrom:(Bookmark*)b
+{
+ if (![[a objectForKey:KEY_NAME] isEqualToString:[b objectForKey:KEY_NAME]] ||
+ ![[a objectForKey:KEY_SHORTCUT] isEqualToString:[b objectForKey:KEY_SHORTCUT]] ||
+ ![[a objectForKey:KEY_TAGS] isEqualToArray:[b objectForKey:KEY_TAGS]] ||
+ ![[a objectForKey:KEY_GUID] isEqualToString:[b objectForKey:KEY_GUID]]) {
+ return YES;
+ } else {
+ return NO;
+ }
+}
+
- (void)setBookmark:(Bookmark*)bookmark atIndex:(int)i
{
Bookmark* orig = [bookmarks_ objectAtIndex:i];
BOOL isDefault = NO;
if ([[orig objectForKey:KEY_GUID] isEqualToString:defaultBookmarkGuid_]) {
isDefault = YES;
}
+
+ Bookmark* before = [bookmarks_ objectAtIndex:i];
+ BOOL needJournal = [self bookmark:bookmark differsJournalablyFrom:before];
+ if (needJournal) {
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_REMOVE bookmark:[bookmarks_ objectAtIndex:i] model:self]];
+ }
[bookmarks_ replaceObjectAtIndex:i withObject:bookmark];
+ if (needJournal) {
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_ADD bookmark:bookmark model:self]];
+ }
if (isDefault) {
[self setDefaultByGuid:[bookmark objectForKey:KEY_GUID]];
}
@@ -328,6 +364,7 @@ - (void)removeAllBookmarks
{
[bookmarks_ removeAllObjects];
defaultBookmarkGuid_ = @"";
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_REMOVE_ALL bookmark:nil model:self]];
[self postChangeNotification];
}
@@ -455,6 +492,9 @@ - (void)setDefaultByGuid:(NSString*)guid
if (prefs_) {
[prefs_ setObject:defaultBookmarkGuid_ forKey:KEY_DEFAULT_GUID];
}
+ [journal_ addObject:[BookmarkJournalEntry journalWithAction:JOURNAL_SET_DEFAULT
+ bookmark:[self defaultBookmark]
+ model:self]];
[self postChangeNotification];
}
@@ -476,7 +516,11 @@ - (void)moveGuid:(NSString*)guid toRow:(int)destinationRow
- (void)postChangeNotification
{
- [[NSNotificationCenter defaultCenter] postNotificationName: @"iTermReloadAddressBook" object: nil userInfo: nil];
+ [[NSNotificationCenter defaultCenter] postNotificationName:@"iTermReloadAddressBook"
+ object:nil
+ userInfo:[NSDictionary dictionaryWithObject:journal_ forKey:@"array"]];
+ [journal_ release];
+ journal_ = [[NSMutableArray alloc] init];
}
- (void)dump
@@ -501,4 +545,240 @@ - (NSArray*)guids
return guids;
}
++ (NSMenu*)findOrCreateTagSubmenuInMenu:(NSMenu*)menu startingAtItem:(int)skip withName:(NSString*)name params:(JournalParams*)params
+{
+ NSArray* items = [menu itemArray];
+ int pos = [menu numberOfItems];
+ int N = pos;
+ for (int i = skip; i < N; i++) {
+ NSMenuItem* cur = [items objectAtIndex:i];
+ if (![cur submenu] || [cur isSeparatorItem]) {
+ pos = i;
+ break;
+ }
+ int comp = [[cur title] caseInsensitiveCompare:name];
+ if (comp == 0) {
+ return [cur submenu];
+ } else if (comp > 0) {
+ pos = i;
+ break;
+ }
+ }
+
+ // Add menu item with submenu
+ NSMenuItem* newItem = [[NSMenuItem alloc] initWithTitle:name action:nil keyEquivalent:@""];
+ [newItem setSubmenu:[[NSMenu alloc] init]];
+ [menu insertItem:newItem atIndex:pos];
+
+ return [newItem submenu];
+}
+
++ (void)addOpenAllToMenu:(NSMenu*)menu params:(JournalParams*)params
+{
+ // Add separator + open all menu items
+ [menu addItem:[NSMenuItem separatorItem]];
+ NSMenuItem* openAll = [menu addItemWithTitle:@"Open All" action:params->openAllSelector keyEquivalent:@""];
+ [openAll setTarget:params->target];
+
+ // Add alternate open all menu
+ NSMenuItem* altOpenAll = [[NSMenuItem alloc] initWithTitle:@"Open All in New Window"
+ action:params->alternateOpenAllSelector
+ keyEquivalent:@""];
+ [altOpenAll setTarget:params->target];
+ [altOpenAll setKeyEquivalentModifierMask:NSAlternateKeyMask];
+ [altOpenAll setAlternate:YES];
+ [altOpenAll setRepresentedObject:gAltOpenAllRepresentedObject];
+ [menu addItem:altOpenAll];
+}
+
++ (BOOL)menuHasOpenAll:(NSMenu*)menu
+{
+ NSArray* items = [menu itemArray];
+ if ([items count] < 3) {
+ return NO;
+ }
+ int n = [items count];
+ return ([[items objectAtIndex:n-1] representedObject] == gAltOpenAllRepresentedObject);
+}
+
+- (int)positionOfBookmark:(Bookmark*)b startingAtItem:(int)skip inMenu:(NSMenu*)menu
+{
+ // Find position of bookmark in menu
+ NSString* name = [b objectForKey:KEY_NAME];
+ int N = [menu numberOfItems];
+ if ([BookmarkModel menuHasOpenAll:menu]) {
+ N -= 3;
+ }
+ NSArray* items = [menu itemArray];
+ int pos = N;
+ for (int i = skip; i < N; i++) {
+ NSMenuItem* cur = [items objectAtIndex:i];
+ if ([cur isSeparatorItem]) {
+ break;
+ }
+ if ([cur isHidden] || [cur submenu]) {
+ continue;
+ }
+ if ([[cur title] caseInsensitiveCompare:name] > 0) {
+ pos = i;
+ break;
+ }
+ }
+
+ return pos;
+}
+
+- (void)addBookmark:(Bookmark*)b
+ toMenu:(NSMenu*)menu
+ atPosition:(int)pos
+ withParams:(JournalParams*)params
+ isAlternate:(BOOL)isAlternate
+{
+ NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:[b objectForKey:KEY_NAME]
+ action:isAlternate ? params->alternateSelector : params->selector
+ keyEquivalent:@""];
+ NSString* shortcut = [b objectForKey:KEY_SHORTCUT];
+ if ([shortcut length]) {
+ [item setKeyEquivalent:[shortcut lowercaseString]];
+ [item setKeyEquivalentModifierMask:NSCommandKeyMask | NSControlKeyMask | (isAlternate ? NSAlternateKeyMask : 0)];
+ } else if (isAlternate) {
+ [item setKeyEquivalentModifierMask:NSAlternateKeyMask];
+ }
+ [item setAlternate:isAlternate];
+ [item setTarget:params->target];
+ [item setRepresentedObject:[[[b objectForKey:KEY_GUID] copy] autorelease]];
+ [menu insertItem:item atIndex:pos];
+}
+
+- (void)addBookmark:(Bookmark*)b toMenu:(NSMenu*)menu startingAtItem:(int)skip withTags:(NSArray*)tags params:(JournalParams*)params
+{
+ int pos = [self positionOfBookmark:b startingAtItem:skip inMenu:menu];
+
+ if (![tags count]) {
+ // Add item & alternate if no tags
+ [self addBookmark:b toMenu:menu atPosition:pos withParams:params isAlternate:NO];
+ [self addBookmark:b toMenu:menu atPosition:pos+1 withParams:params isAlternate:YES];
+ }
+
+ // Add to tag submenus
+ for (NSString* tag in [NSSet setWithArray:tags]) {
+ NSMenu* tagSubMenu = [BookmarkModel findOrCreateTagSubmenuInMenu:menu
+ startingAtItem:skip
+ withName:tag
+ params:params];
+ [self addBookmark:b toMenu:tagSubMenu startingAtItem:0 withTags:nil params:params];
+ }
+
+ if ([menu numberOfItems] > skip + 2 && ![BookmarkModel menuHasOpenAll:menu]) {
+ [BookmarkModel addOpenAllToMenu:menu params:params];
+ }
+}
+
++ (void)applyAddJournalEntry:(BookmarkJournalEntry*)e toMenu:(NSMenu*)menu startingAtItem:(int)skip params:(JournalParams*)params
+{
+ BookmarkModel* model = e->model;
+ Bookmark* b = [model bookmarkWithGuid:e->guid];
+ if (!b) {
+ return;
+ }
+ [model addBookmark:b toMenu:menu startingAtItem:skip withTags:[b objectForKey:KEY_TAGS] params:params];
+}
+
++ (void)applyRemoveJournalEntry:(BookmarkJournalEntry*)e toMenu:(NSMenu*)menu startingAtItem:(int)skip params:(JournalParams*)params
+{
+ int pos = [menu indexOfItemWithRepresentedObject:e->guid];
+ if (pos != -1) {
+ [menu removeItemAtIndex:pos];
+ [menu removeItemAtIndex:pos];
+ }
+
+ // Remove bookmark from each tag it belongs to
+ for (NSString* tag in e->tags) {
+ NSMenuItem* item = [menu itemWithTitle:tag];
+ NSMenu* submenu = [item submenu];
+ if (submenu) {
+ [BookmarkModel applyRemoveJournalEntry:e toMenu:submenu startingAtItem:0 params:params];
+ if ([submenu numberOfItems] == 0) {
+ [menu removeItem:item];
+ }
+ }
+ }
+
+ // Remove "open all" section if it's no longer needed.
+ // [0, ..., skip-1, bm1, bm1alt, separator, open all, open all alternate]
+ if (([BookmarkModel menuHasOpenAll:menu] && [menu numberOfItems] <= skip + 5)) {
+ [menu removeItemAtIndex:[menu numberOfItems] - 1];
+ [menu removeItemAtIndex:[menu numberOfItems] - 1];
+ [menu removeItemAtIndex:[menu numberOfItems] - 1];
+ }
+}
+
++ (void)applyRemoveAllJournalEntry:(BookmarkJournalEntry*)e toMenu:(NSMenu*)menu startingAtItem:(int)skip params:(JournalParams*)params
+{
+ while ([menu numberOfItems] > skip) {
+ [menu removeItemAtIndex:[menu numberOfItems] - 1];
+ }
+}
+
++ (void)applySetDefaultJournalEntry:(BookmarkJournalEntry*)e toMenu:(NSMenu*)menu startingAtItem:(int)skip params:(JournalParams*)params
+{
+}
+
++ (void)applyJournal:(NSDictionary*)journalDict toMenu:(NSMenu*)menu startingAtItem:(int)skip params:(JournalParams*)params
+{
+ NSArray* journal = [journalDict objectForKey:@"array"];
+ for (BookmarkJournalEntry* e in journal) {
+ switch (e->action) {
+ case JOURNAL_ADD:
+ [BookmarkModel applyAddJournalEntry:e toMenu:menu startingAtItem:skip params:params];
+ break;
+
+ case JOURNAL_REMOVE:
+ [BookmarkModel applyRemoveJournalEntry:e toMenu:menu startingAtItem:skip params:params];
+ break;
+
+ case JOURNAL_REMOVE_ALL:
+ [BookmarkModel applyRemoveAllJournalEntry:e toMenu:menu startingAtItem:skip params:params];
+ break;
+
+ case JOURNAL_SET_DEFAULT:
+ [BookmarkModel applySetDefaultJournalEntry:e toMenu:menu startingAtItem:skip params:params];
+ break;
+
+ default:
+ assert(false);
+ }
+ }
+}
+
++ (void)applyJournal:(NSDictionary*)journal toMenu:(NSMenu*)menu params:(JournalParams*)params
+{
+ [BookmarkModel applyJournal:journal toMenu:menu startingAtItem:0 params:params];
+}
+
+
+@end
+
+@implementation BookmarkJournalEntry
+
+
++ (BookmarkJournalEntry*)journalWithAction:(JournalAction)action
+ bookmark:(Bookmark*)bookmark
+ model:(BookmarkModel*)model
+{
+ BookmarkJournalEntry* entry = [[[BookmarkJournalEntry alloc] init] autorelease];
+ entry->action = action;
+ entry->guid = [[bookmark objectForKey:KEY_GUID] copy];
+ entry->model = model;
+ entry->tags = [[NSArray alloc] initWithArray:[bookmark objectForKey:KEY_TAGS]];
+ return entry;
+}
+
+- (void)dealloc
+{
+ [guid release];
+ [tags release];
+ [super dealloc];
+}
+
@end
View
46 Headers/iTerm/BookmarkModel.h
@@ -23,14 +23,25 @@
*/
#import <Cocoa/Cocoa.h>
-
+
#define BMKEY_BOOKMARKS_ARRAY @"Bookmarks Array"
typedef NSDictionary Bookmark;
+typedef struct {
+ SEL selector; // normal action
+ SEL alternateSelector; // opt+click
+ SEL openAllSelector; // open all bookmarks
+ SEL alternateOpenAllSelector; // opt+open all bookmarks
+ id target; // receiver of selector
+} JournalParams;
@interface BookmarkModel : NSObject {
NSMutableArray* bookmarks_;
NSString* defaultBookmarkGuid_;
+
+ // The journal is an array of actions since the last change notification was
+ // posted.
+ NSMutableArray* journal_;
NSUserDefaults* prefs_;
}
@@ -69,7 +80,40 @@ typedef NSDictionary Bookmark;
- (void)dump;
- (NSArray*)bookmarks;
- (NSArray*)guids;
+- (void)addBookmark:(Bookmark*)b toMenu:(NSMenu*)menu startingAtItem:(int)skip withTags:(NSArray*)tags params:(JournalParams*)params;
// Tell all listeners that the model has changed.
- (void)postChangeNotification;
+
++ (void)applyJournal:(NSDictionary*)journal
+ toMenu:(NSMenu*)menu
+ startingAtItem:(int)skip
+ params:(JournalParams*)params;
+
++ (void)applyJournal:(NSDictionary*)journal
+ toMenu:(NSMenu*)menu
+ params:(JournalParams*)params;
+
+@end
+
+typedef enum {
+ JOURNAL_ADD,
+ JOURNAL_REMOVE,
+ JOURNAL_REMOVE_ALL,
+ JOURNAL_SET_DEFAULT
+} JournalAction;
+
+@interface BookmarkJournalEntry : NSObject {
+ @public
+ JournalAction action;
+ NSString* guid;
+ BookmarkModel* model;
+ // Tags before the action was applied.
+ NSArray* tags;
+}
+
++ (BookmarkJournalEntry*)journalWithAction:(JournalAction)action
+ bookmark:(Bookmark*)bookmark
+ model:(BookmarkModel*)model;
+
@end
View
3 Headers/iTerm/iTermController.h
@@ -95,7 +95,8 @@
- (PseudoTerminal *)currentTerminal;
- (void)terminalWillClose:(PseudoTerminal*)theTerminalWindow;
- (NSArray*)sortedEncodingList;
-- (void)addBookmarksToMenu:(NSMenu *)aMenu target:(id)aTarget withShortcuts:(BOOL)withShortcuts selector:(SEL)selector openAllSelector:(SEL)openAllSelector alternateSelector:(SEL)alternateSeelctor;
+- (void)addBookmarksToMenu:(NSMenu *)aMenu;
+- (void)addBookmarksToMenu:(NSMenu *)aMenu withSelector:(SEL)selector openAllSelector:(SEL)openAllSelector;
- (id)launchBookmark:(NSDictionary*)bookmarkData inTerminal:(PseudoTerminal*)theTerm;
- (id)launchBookmark:(NSDictionary *)bookmarkData inTerminal:(PseudoTerminal *)theTerm withCommand:(NSString *)command;
- (id)launchBookmark:(NSDictionary*)bookmarkData inTerminal:(PseudoTerminal*)theTerm withURL:(NSString*)url;
View
4 Headers/iTerm/iTermKeyBindingMgr.h
@@ -224,7 +224,9 @@
+ (BOOL)haveKeyMappingForKeyString:(NSString*)keyString inBookmark:(Bookmark*)bookmark;
// Remove any keymappings that reference a guid from either a bookmark or the global
-// keymappings (if bookmark is nil).
+// keymappings (if bookmark is nil). If a bookmark is specified but no change is made then
+// it returns nil. If a bookmark is specified and changed, an autorelease copy of the modified
+// bookmark is returned.
+ (Bookmark*)removeMappingsReferencingGuid:(NSString*)guid fromBookmark:(Bookmark*)bookmark;
@end
View
6 PTToolbarController.h
@@ -4,7 +4,7 @@
** Copyright (c) 2002, 2003
**
** Author: Fabian, Ujwal S. Setlur
- ** Initial code by Kiichi Kusama
+ ** Initial code by Kiichi Kusama
**
** Project: iTerm
**
@@ -35,10 +35,12 @@ extern NSString *CommandToolbarItem;
@class PseudoTerminal;
-@interface PTToolbarController : NSObject
+@interface PTToolbarController : NSObject
{
NSToolbar* _toolbar;
PseudoTerminal* _pseudoTerminal;
+ NSMenu* iconMenu_;
+ NSMenu* textMenu_;
}
- (id)initWithPseudoTerminal:(PseudoTerminal*)terminal;
View
39 PTToolbarController.m
@@ -63,6 +63,8 @@ - (id)initWithPseudoTerminal:(PseudoTerminal*)terminal;
- (void)dealloc;
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ [iconMenu_ release];
+ [textMenu_ release];
[_toolbar release];
[super dealloc];
}
@@ -251,18 +253,13 @@ - (void)buildToolbarItemPopUpMenu:(NSToolbarItem *)toolbarItem forToolbar:(NSToo
[self _removeItemsFromMenu:[[toolbarItem menuFormRepresentation] submenu]];
[aPopUpButton addItemWithTitle: @""];
- aMenu = [[NSMenu alloc] init];
+ [iconMenu_ release];
+ iconMenu_ = aMenu = [[NSMenu alloc] init];
// first menu item is just a space taker
[aMenu addItem: [[[NSMenuItem alloc] initWithTitle: @"AAA" action:@selector(newSessionInTabAtIndex:) keyEquivalent:@""] autorelease]];
- [[iTermController sharedInstance] addBookmarksToMenu:aMenu
- target:_pseudoTerminal
- withShortcuts:NO
- selector:@selector(newSessionInTabAtIndex:)
- openAllSelector:@selector(newSessionsInWindow:)
- alternateSelector:nil];
+ [[iTermController sharedInstance] addBookmarksToMenu:aMenu];
- [aPopUpButton setMenu: aMenu];
- [aMenu release];
+ [aPopUpButton setMenu:aMenu];
// Now set the icon
item = [[aPopUpButton cell] menuItem];
@@ -285,15 +282,10 @@ - (void)buildToolbarItemPopUpMenu:(NSToolbarItem *)toolbarItem forToolbar:(NSToo
// build a menu representation for text only.
item = [[NSMenuItem alloc] initWithTitle: NSLocalizedStringFromTableInBundle(@"New Tab",@"iTerm", [NSBundle bundleForClass: [self class]], @"Toolbar Item:New") action: nil keyEquivalent: @""];
- aMenu = [[NSMenu alloc] init];
- [[iTermController sharedInstance] addBookmarksToMenu:aMenu
- target:_pseudoTerminal
- withShortcuts:NO
- selector:@selector(newSessionInTabAtIndex:)
- openAllSelector:@selector(newSessionsInWindow:)
- alternateSelector:nil];
- [item setSubmenu: aMenu];
- [aMenu release];
+ [textMenu_ release];
+ textMenu_ = aMenu = [[NSMenu alloc] init];
+ [[iTermController sharedInstance] addBookmarksToMenu:aMenu];
+ [item setSubmenu:aMenu];
[toolbarItem setMenuFormRepresentation: item];
[item release];
@@ -305,7 +297,16 @@ - (void)reloadAddressBookMenu:(NSNotification *)aNotification
NSToolbarItem *aToolbarItem = [self toolbarItemWithIdentifier:NewToolbarItem];
if (aToolbarItem) {
- [self buildToolbarItemPopUpMenu:aToolbarItem forToolbar:_toolbar];
+ JournalParams params;
+ params.selector = @selector(newSessionInTabAtIndex:);
+ params.openAllSelector = @selector(newSessionsInWindow:);
+ params.alternateSelector = @selector(newSessionInTabAtIndex:);
+ params.alternateOpenAllSelector = @selector(newSessionsInWindow:);
+ params.target = self;
+
+ [BookmarkModel applyJournal:[aNotification userInfo] toMenu:iconMenu_ params:&params];
+ [BookmarkModel applyJournal:[aNotification userInfo] toMenu:textMenu_ params:&params];
+ //[self buildToolbarItemPopUpMenu:aToolbarItem forToolbar:_toolbar];
}
}
View
8 PreferencePanel.m
@@ -2974,12 +2974,16 @@ - (void)_removeKeyMappingsReferringToBookmarkGuid:(NSString*)badRef
for (NSString* guid in [[BookmarkModel sharedInstance] guids]) {
Bookmark* bookmark = [[BookmarkModel sharedInstance] bookmarkWithGuid:guid];
bookmark = [iTermKeyBindingMgr removeMappingsReferencingGuid:badRef fromBookmark:bookmark];
- [[BookmarkModel sharedInstance] setBookmark:bookmark withGuid:guid];
+ if (bookmark) {
+ [[BookmarkModel sharedInstance] setBookmark:bookmark withGuid:guid];
+ }
}
for (NSString* guid in [[BookmarkModel sessionsInstance] guids]) {
Bookmark* bookmark = [[BookmarkModel sessionsInstance] bookmarkWithGuid:guid];
bookmark = [iTermKeyBindingMgr removeMappingsReferencingGuid:badRef fromBookmark:bookmark];
- [[BookmarkModel sessionsInstance] setBookmark:bookmark withGuid:guid];
+ if (bookmark) {
+ [[BookmarkModel sessionsInstance] setBookmark:bookmark withGuid:guid];
+ }
}
[iTermKeyBindingMgr removeMappingsReferencingGuid:badRef fromBookmark:nil];
[[PreferencePanel sharedInstance]->keyMappings reloadData];
View
17 PseudoTerminal.m
@@ -1551,25 +1551,16 @@ - (void)menuForEvent:(NSEvent *)theEvent menu:(NSMenu *)theMenu
// Build the bookmarks menu
NSMenu *aMenu = [[[NSMenu alloc] init] autorelease];
- // TODO: test this
[[iTermController sharedInstance] addBookmarksToMenu:aMenu
- target:[iTermController sharedInstance]
- withShortcuts:NO
- selector:@selector(newSessionInWindowAtIndex:)
- openAllSelector:@selector(newSessionsInManyWindows:)
- alternateSelector:nil];
- [aMenu addItem: [NSMenuItem separatorItem]];
+ withSelector:@selector(newSessionInWindowAtIndex:)
+ openAllSelector:@selector(newSessionsInNewWindow:)];
[theMenu setSubmenu:aMenu forItem:[theMenu itemAtIndex:0]];
aMenu = [[[NSMenu alloc] init] autorelease];
[[iTermController sharedInstance] addBookmarksToMenu:aMenu
- target:self
- withShortcuts:NO
- selector:@selector(newSessionInTabAtIndex:)
- openAllSelector:@selector(newSessionsInManyTabsAtIndex:)
- alternateSelector:nil];
- [aMenu addItem: [NSMenuItem separatorItem]];
+ withSelector:@selector(newSessionInTabAtIndex:)
+ openAllSelector:@selector(newSessionsInWindow:)];
[theMenu setSubmenu:aMenu forItem:[theMenu itemAtIndex:1]];
}
View
1 iTerm.xcodeproj/project.pbxproj
@@ -1167,6 +1167,7 @@
isa = PBXProject;
buildConfigurationList = BB024D39096EE4080021E793 /* Build configuration list for PBXProject "iTerm" */;
compatibilityVersion = "Xcode 3.1";
+ developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
View
2 iTermApplicationDelegate.h
@@ -92,6 +92,7 @@ void DebugLog(NSString* value);
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename;
- (BOOL)applicationOpenUntitledFile:(NSApplication *)app;
- (NSMenu *)applicationDockMenu:(NSApplication *)sender;
+- (NSMenu*)bookmarksMenu;
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)app;
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag;
@@ -132,7 +133,6 @@ void DebugLog(NSString* value);
// Notifications
- (void) reloadMenus: (NSNotification *) aNotification;
- (void) buildSessionSubmenu: (NSNotification *) aNotification;
-- (void) buildAddressBookMenu: (NSNotification *) aNotification;
- (void) reloadSessionMenus: (NSNotification *) aNotification;
- (void) nonTerminalWindowBecameKey: (NSNotification *) aNotification;
View
50 iTermApplicationDelegate.m
@@ -102,8 +102,6 @@ - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
CFSTR(""),
kCFPreferencesCurrentApplication);
- [self buildAddressBookMenu:nil];
-
PreferencePanel* ppanel = [PreferencePanel sharedInstance];
if ([ppanel hotkey]) {
[[iTermController sharedInstance] registerHotkey:[ppanel hotkeyCode] modifiers:[ppanel hotkeyModifiers]];
@@ -282,7 +280,7 @@ - (id)init
object:nil];
[[NSNotificationCenter defaultCenter] addObserver: self
- selector: @selector(buildAddressBookMenu:)
+ selector: @selector(updateAddressBookMenu:)
name: @"iTermReloadAddressBook"
object: nil];
@@ -407,15 +405,15 @@ - (void)_newSessionMenu:(NSMenu*)superMenu title:(NSString*)title target:(id)aTa
// Build the bookmark menu
bookmarksMenu = [[[NSMenu alloc] init] autorelease];
- [[iTermController sharedInstance] addBookmarksToMenu:bookmarksMenu
- target:aTarget
- withShortcuts:NO
- selector:selector
- openAllSelector:openAllSelector
- alternateSelector:nil];
+ [[iTermController sharedInstance] addBookmarksToMenu:bookmarksMenu withSelector:selector openAllSelector:openAllSelector];
[newMenuItem setSubmenu:bookmarksMenu];
}
+- (NSMenu*)bookmarksMenu
+{
+ return bookmarkMenu;
+}
+
- (NSMenu *)applicationDockMenu:(NSApplication *)sender
{
NSMenu* aMenu = [[NSMenu alloc] initWithTitle: @"Dock Menu"];
@@ -425,7 +423,7 @@ - (NSMenu *)applicationDockMenu:(NSApplication *)sender
[self _newSessionMenu:aMenu title:@"New Window"
target:[iTermController sharedInstance]
selector:@selector(newSessionInWindowAtIndex:)
- openAllSelector:@selector(newSessionsInManyWindows:)];
+ openAllSelector:@selector(newSessionsInNewWindow:)];
[self _newSessionMenu:aMenu title:@"New Tab"
target:frontTerminal
selector:@selector(newSessionInTabAtIndex:)
@@ -662,7 +660,6 @@ - (void)reloadMenus:(NSNotification *)aNotification
[nextTerminal setAction: (frontTerminal ? @selector(nextTerminal:) : nil)];
[self buildSessionSubmenu: aNotification];
- [self buildAddressBookMenu: aNotification];
// reset the close tab/window shortcuts
[closeTab setAction:@selector(closeCurrentTab:)];
[closeTab setTarget:frontTerminal];
@@ -748,28 +745,19 @@ - (void)_removeItemsFromMenu:(NSMenu*)menu
}
}
-- (void)buildAddressBookMenu:(NSNotification *)aNotification
+- (void)updateAddressBookMenu:(NSNotification*)aNotification
{
- // clear Bookmark menu
- const int kNumberOfStaticMenuItems = 5;
- for (; [bookmarkMenu numberOfItems] > kNumberOfStaticMenuItems;) {
- NSMenuItem* anItem = [bookmarkMenu itemAtIndex:kNumberOfStaticMenuItems];
- [anItem retain];
- [bookmarkMenu removeItemAtIndex:kNumberOfStaticMenuItems];
- NSMenu* sub = [anItem submenu];
- if (sub) {
- [self _removeItemsFromMenu:sub];
- }
- [anItem release];
- }
+ JournalParams params;
+ params.selector = @selector(newSessionInTabAtIndex:);
+ params.openAllSelector = @selector(newSessionsInWindow:);
+ params.alternateSelector = @selector(newSessionInWindowAtIndex:);
+ params.alternateOpenAllSelector = @selector(newSessionsInWindow:);
+ params.target = [iTermController sharedInstance];
- // add bookmarks into Bookmark menu
- [[iTermController sharedInstance] addBookmarksToMenu:bookmarkMenu
- target:[[iTermController sharedInstance] currentTerminal]
- withShortcuts:YES
- selector:@selector(newSessionInTabAtIndex:)
- openAllSelector:@selector(newSessionsInWindow:)
- alternateSelector:@selector(newSessionInWindowAtIndex:)];
+ [BookmarkModel applyJournal:[aNotification userInfo]
+ toMenu:bookmarkMenu
+ startingAtItem:5
+ params:&params];
}
// This is called whenever a tab becomes key or logging starts/stops.
View
119 iTermController.m
@@ -584,27 +584,42 @@ - (void)_newSessionsInManyWindowsInMenu:(NSMenu*)parent
- (void)newSessionsInManyWindows:(id)sender
{
- [self _newSessionsInManyWindowsInMenu:[sender representedObject]];
+ [self _newSessionsInManyWindowsInMenu:[sender menu]];
}
-- (PseudoTerminal*)_openNewSessionsFromMenu:(NSMenu*)parent inNewWindow:(BOOL)newWindow
+- (PseudoTerminal*)_openNewSessionsFromMenu:(NSMenu*)parent inNewWindow:(BOOL)newWindow usedGuids:(NSMutableSet*)usedGuids bookmarks:(NSMutableArray*)bookmarks
{
+ BOOL doOpen = usedGuids == nil;
+ if (doOpen) {
+ usedGuids = [NSMutableSet setWithCapacity:[[BookmarkModel sharedInstance] numberOfBookmarks]];
+ bookmarks = [NSMutableArray arrayWithCapacity:[[BookmarkModel sharedInstance] numberOfBookmarks]];
+ }
+
PseudoTerminal* term = newWindow ? nil : [self currentTerminal];
for (NSMenuItem* item in [parent itemArray]) {
if (![item isSeparatorItem] && ![item submenu] && ![item isAlternate]) {
NSString* guid = [item representedObject];
Bookmark* bookmark = [[BookmarkModel sharedInstance] bookmarkWithGuid:guid];
if (bookmark) {
- if (!term) {
- PTYSession* session = [self launchBookmark:bookmark inTerminal:nil];
- term = [[session tab] realParentWindow];
- } else {
- [self launchBookmark:bookmark inTerminal:term];
+ if (![usedGuids containsObject:guid]) {
+ [usedGuids addObject:guid];
+ [bookmarks addObject:bookmark];
}
}
} else if (![item isSeparatorItem] && [item submenu] && ![item isAlternate]) {
NSMenu* sub = [item submenu];
- term = [self _openNewSessionsFromMenu:sub inNewWindow:(term == nil)];
+ term = [self _openNewSessionsFromMenu:sub inNewWindow:newWindow usedGuids:usedGuids bookmarks:bookmarks];
+ }
+ }
+
+ if (doOpen) {
+ for (Bookmark* bookmark in bookmarks) {
+ if (!term) {
+ PTYSession* session = [self launchBookmark:bookmark inTerminal:nil];
+ term = [[session tab] realParentWindow];
+ } else {
+ [self launchBookmark:bookmark inTerminal:term];
+ }
}
}
@@ -613,73 +628,43 @@ - (PseudoTerminal*)_openNewSessionsFromMenu:(NSMenu*)parent inNewWindow:(BOOL)ne
- (void)newSessionsInWindow:(id)sender
{
- [self _openNewSessionsFromMenu:[sender representedObject] inNewWindow:[sender isAlternate]];
+ [self _openNewSessionsFromMenu:[sender menu] inNewWindow:[sender isAlternate] usedGuids:nil bookmarks:nil];
}
-- (void)addBookmarksToMenu:(NSMenu *)aMenu target:(id)aTarget withShortcuts:(BOOL)withShortcuts selector:(SEL)selector openAllSelector:(SEL)openAllSelector alternateSelector:(SEL)alternateSelector
+- (void)newSessionsInNewWindow:(id)sender
{
- NSArray* tags = [[BookmarkModel sharedInstance] allTags];
- int count = 0;
- NSArray* sortedTags = [tags sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
- for (int i = 0; i < [sortedTags count]; ++i) {
- [self _addBookmarksForTag:[sortedTags objectAtIndex:i]
- toMenu:aMenu
- target:aTarget
- withShortcuts:withShortcuts
- selector:selector
- alternateSelector:alternateSelector
- openAllSelector:openAllSelector];
- ++count;
- }
- for (int i = 0; i < [[BookmarkModel sharedInstance] numberOfBookmarks]; ++i) {
- Bookmark* bookmark = [[BookmarkModel sharedInstance] bookmarkAtIndex:i];
- if ([[bookmark objectForKey:KEY_TAGS] count] == 0) {
- ++count;
- [self _addBookmark:bookmark
- toMenu:aMenu
- target:aTarget
- withShortcuts:withShortcuts
- selector:selector
- alternateSelector:alternateSelector];
- }
- }
+ [self _openNewSessionsFromMenu:[sender menu] inNewWindow:YES
+ usedGuids:nil bookmarks:nil];
+}
- if (count > 1) {
- [aMenu addItem:[NSMenuItem separatorItem]];
- NSMenuItem* aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Open All"
- action:openAllSelector
- keyEquivalent:@""];
- unsigned int modifierMask = NSCommandKeyMask | NSControlKeyMask;
- [aMenuItem setKeyEquivalentModifierMask:modifierMask];
- [aMenuItem setRepresentedObject:aMenu];
- if ([self respondsToSelector:openAllSelector]) {
- [aMenuItem setTarget:self];
- } else {
- assert([aTarget respondsToSelector:openAllSelector]);
- [aMenuItem setTarget:aTarget];
- }
- [aMenu addItem:aMenuItem];
- [aMenuItem release];
+- (void)addBookmarksToMenu:(NSMenu *)aMenu withSelector:(SEL)selector openAllSelector:(SEL)openAllSelector
+{
+ JournalParams params;
+ params.selector = selector;
+ params.openAllSelector = openAllSelector;
+ params.alternateSelector = @selector(newSessionInWindowAtIndex:);
+ params.alternateOpenAllSelector = @selector(newSessionsInWindow:);
+ params.target = self;
- // Add alternate -------------------------------------------------------
- aMenuItem = [[NSMenuItem alloc] initWithTitle:@"Open All in New Window"
- action:openAllSelector
- keyEquivalent:@""];
- modifierMask = NSCommandKeyMask | NSControlKeyMask;
- [aMenuItem setAlternate:YES];
- [aMenuItem setKeyEquivalentModifierMask:modifierMask | NSAlternateKeyMask];
- [aMenuItem setRepresentedObject:aMenu];
- if ([self respondsToSelector:openAllSelector]) {
- [aMenuItem setTarget:self];
- } else {
- assert([aTarget respondsToSelector:openAllSelector]);
- [aMenuItem setTarget:aTarget];
- }
- [aMenu addItem:aMenuItem];
- [aMenuItem release];
+ BookmarkModel* bm = [BookmarkModel sharedInstance];
+ int N = [bm numberOfBookmarks];
+ for (int i = 0; i < N; i++) {
+ Bookmark* b = [bm bookmarkAtIndex:i];
+ [bm addBookmark:b
+ toMenu:aMenu
+ startingAtItem:0
+ withTags:[b objectForKey:KEY_TAGS]
+ params:&params];
}
}
+- (void)addBookmarksToMenu:(NSMenu *)aMenu
+{
+ [self addBookmarksToMenu:aMenu
+ withSelector:@selector(newSessionInTabAtIndex:)
+ openAllSelector:@selector(newSessionsInWindow:)];
+}
+
- (void)irAdvance:(int)dir
{
[FRONT irAdvance:dir];
View
8 iTermKeyBindingMgr.m
@@ -894,6 +894,7 @@ + (Bookmark*)removeMappingsReferencingGuid:(NSString*)guid fromBookmark:(Bookmar
{
if (bookmark) {
NSMutableDictionary* mutableBookmark = [NSMutableDictionary dictionaryWithDictionary:bookmark];
+ BOOL anyChange = NO;
BOOL change;
do {
change = NO;
@@ -908,12 +909,17 @@ + (Bookmark*)removeMappingsReferencingGuid:(NSString*)guid fromBookmark:(Bookmar
if ([referencedGuid isEqualToString:guid]) {
[iTermKeyBindingMgr removeMappingAtIndex:i inBookmark:mutableBookmark];
change = YES;
+ anyChange = YES;
break;
}
}
}
} while (change);
- return mutableBookmark;
+ if (!anyChange) {
+ return nil;
+ } else {
+ return mutableBookmark;
+ }
} else {
BOOL change;
do {

0 comments on commit 638e091

Please sign in to comment.
Something went wrong with that request. Please try again.