зеркало из https://github.com/mozilla/pjs.git
Merging changes from CHIMERA_M1_0_1_BRANCH.
This commit is contained in:
Родитель
41dc25b8ff
Коммит
b434ea0790
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>646 106 458 263 0 0 1600 1002 </string>
|
||||
<string>674 107 458 263 0 0 1600 1002 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>214</key>
|
||||
|
@ -12,6 +12,6 @@
|
|||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6D52</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичные данные
camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib
сгенерированный
Двоичные данные
camino/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
|
@ -17,11 +17,7 @@
|
|||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>8</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичные данные
camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib
сгенерированный
Двоичные данные
camino/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
Двоичный файл не отображается.
Двоичный файл не отображается.
|
@ -68,6 +68,7 @@
|
|||
closeCurrentTab = id;
|
||||
closeOtherTabs = id;
|
||||
closeSendersTab = id;
|
||||
copyImage = id;
|
||||
copyImageLocation = id;
|
||||
copyLinkLocation = id;
|
||||
endAddBookmarkSheet = id;
|
||||
|
@ -80,6 +81,7 @@
|
|||
goToLocationFromToolbarURLField = id;
|
||||
home = id;
|
||||
manageBookmarks = id;
|
||||
manageHistory = id;
|
||||
moveTabToNewWindow = id;
|
||||
newTab = id;
|
||||
nextTab = id;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>66 21 653 383 0 0 1152 848 </string>
|
||||
<string>65 36 653 383 0 0 1152 848 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>124</key>
|
||||
|
@ -15,17 +15,17 @@
|
|||
<key>297</key>
|
||||
<string>107 466 213 294 0 0 1600 1002 </string>
|
||||
<key>314</key>
|
||||
<string>73 542 213 132 0 0 1600 1002 </string>
|
||||
<string>72 544 213 150 0 0 1600 1002 </string>
|
||||
<key>336</key>
|
||||
<string>486 756 213 180 0 0 1600 1002 </string>
|
||||
<key>365</key>
|
||||
<string>31 719 93 162 0 0 1600 1002 </string>
|
||||
<key>463</key>
|
||||
<string>97 693 213 246 0 0 1600 1002 </string>
|
||||
<string>349 487 213 246 0 0 1600 1002 </string>
|
||||
<key>56</key>
|
||||
<string>450 634 343 68 0 0 1280 1002 </string>
|
||||
<key>654</key>
|
||||
<string>206 785 198 144 0 0 1600 1002 </string>
|
||||
<string>140 644 198 144 0 0 1152 848 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
|
@ -42,6 +42,6 @@
|
|||
<key>IBLockedObjects</key>
|
||||
<array/>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичные данные
camino/resources/localized/English.lproj/BrowserWindow.nib/objects.nib
сгенерированный
Двоичные данные
camino/resources/localized/English.lproj/BrowserWindow.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
IBClasses = (
|
||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{CLASS = KeychainBrowserListener; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
ACTIONS = {hitButtonCancel = id; hitButtonOK = id; hitButtonOther = id; shutdown = id; };
|
||||
CLASS = KeychainService;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {confirmChangePasswordPanel = id; confirmStorePasswordPanel = id; };
|
||||
SUPERCLASS = NSObject;
|
||||
}
|
||||
);
|
||||
IBVersion = 1;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>240 146 356 240 0 0 1024 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>283.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
</dict>
|
||||
</plist>
|
Двоичные данные
camino/resources/localized/English.lproj/Localizable.strings
Двоичные данные
camino/resources/localized/English.lproj/Localizable.strings
Двоичный файл не отображается.
|
@ -20,6 +20,7 @@
|
|||
doReload = id;
|
||||
doSearch = id;
|
||||
doStop = id;
|
||||
downloadsWindow = id;
|
||||
exportBookmarks = id;
|
||||
feedbackLink = id;
|
||||
findAgain = id;
|
||||
|
@ -61,7 +62,6 @@
|
|||
mCreateBookmarksFolderMenuItem = NSMenuItem;
|
||||
mCreateBookmarksSeparatorMenuItem = NSMenuItem;
|
||||
mDockMenu = NSMenu;
|
||||
mFilterList = NSPopUpButton;
|
||||
mFilterView = NSView;
|
||||
mGoMenu = NSMenu;
|
||||
mServersSubmenu = NSMenu;
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>237 33 482 372 0 0 1600 1002 </string>
|
||||
<string>105 33 482 372 0 0 1600 1002 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>266</key>
|
||||
<string>437 533 277 90 0 0 1152 848 </string>
|
||||
<string>644 623 277 90 0 0 1600 1002 </string>
|
||||
<key>29</key>
|
||||
<string>11 957 446 44 0 0 1600 1002 </string>
|
||||
<key>494</key>
|
||||
|
@ -31,7 +31,11 @@
|
|||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>2</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>29</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичный файл не отображается.
|
@ -1,18 +1,40 @@
|
|||
{
|
||||
IBClasses = (
|
||||
{
|
||||
CLASS = CHStackView;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mDataSource = id; };
|
||||
SUPERCLASS = NSView;
|
||||
},
|
||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{CLASS = NSObject; LANGUAGE = ObjC; },
|
||||
{CLASS = NSView; LANGUAGE = ObjC; SUPERCLASS = NSResponder; },
|
||||
{
|
||||
CLASS = ProgressDlgController;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mElapsedTimeLabel = NSTextField;
|
||||
mFromField = NSTextField;
|
||||
mProgressBar = NSProgressIndicator;
|
||||
mStatusLabel = NSTextField;
|
||||
mTimeLeftLabel = NSTextField;
|
||||
mToField = NSTextField;
|
||||
mNoDownloadsText = NSTextField;
|
||||
mScrollView = NSScrollView;
|
||||
mStackView = CHStackView;
|
||||
};
|
||||
SUPERCLASS = NSWindowController;
|
||||
},
|
||||
{
|
||||
ACTIONS = {stop = id; toggleDisclosure = id; };
|
||||
CLASS = ProgressViewController;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mLocationsLabel = NSTextField;
|
||||
mLocationsLabelCompact = NSTextField;
|
||||
mProgressBar = NSProgressIndicator;
|
||||
mProgressView = NSView;
|
||||
mProgressViewCompact = NSView;
|
||||
mServerLabel = NSTextField;
|
||||
mStatusLabel = NSTextField;
|
||||
mTimeLeftLabel = NSTextField;
|
||||
mTimeLeftLabelCompact = NSTextField;
|
||||
};
|
||||
SUPERCLASS = NSObject;
|
||||
}
|
||||
);
|
||||
IBVersion = 1;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>94 26 404 250 0 0 1152 746 </string>
|
||||
<string>24 42 592 284 0 0 1600 1002 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<string>286.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5S60</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичные данные
camino/resources/localized/English.lproj/ProgressDialog.nib/objects.nib
сгенерированный
Двоичные данные
camino/resources/localized/English.lproj/ProgressDialog.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
22
camino/resources/localized/English.lproj/ProgressView.nib/classes.nib
сгенерированный
Normal file
22
camino/resources/localized/English.lproj/ProgressView.nib/classes.nib
сгенерированный
Normal file
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
IBClasses = (
|
||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
ACTIONS = {close = id; open = id; reveal = id; stop = id; toggleDisclosure = id; };
|
||||
CLASS = ProgressViewController;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mCompletedView = NSView;
|
||||
mCompletedViewCompact = NSView;
|
||||
mExpandedCancelButton = NSButton;
|
||||
mExpandedOpenButton = NSButton;
|
||||
mExpandedRevealButton = NSButton;
|
||||
mProgressBar = NSProgressIndicator;
|
||||
mProgressView = NSView;
|
||||
mProgressViewCompact = NSView;
|
||||
};
|
||||
SUPERCLASS = NSObject;
|
||||
}
|
||||
);
|
||||
IBVersion = 1;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>75 299 448 284 0 0 1600 1002 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>27</key>
|
||||
<string>573 628 420 80 0 0 1600 1002 </string>
|
||||
<key>5</key>
|
||||
<string>573 564 420 208 0 0 1600 1002 </string>
|
||||
<key>71</key>
|
||||
<string>573 564 420 208 0 0 1600 1002 </string>
|
||||
<key>97</key>
|
||||
<string>573 628 420 80 0 0 1600 1002 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
Двоичные данные
camino/resources/localized/English.lproj/ProgressView.nib/objects.nib
сгенерированный
Normal file
Двоичные данные
camino/resources/localized/English.lproj/ProgressView.nib/objects.nib
сгенерированный
Normal file
Двоичный файл не отображается.
|
@ -3,13 +3,9 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>410 67 356 301 0 0 1152 848 </string>
|
||||
<string>325 55 356 301 0 0 1024 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>251</integer>
|
||||
</array>
|
||||
<string>283.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
</dict>
|
||||
|
|
Двоичный файл не отображается.
|
@ -37,10 +37,14 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "SecurityDialogs.h"
|
||||
#import "CocoaPromptService.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#import "KeychainService.h"
|
||||
#import "nsDownloadListener.h"
|
||||
#import "ProgressDlgController.h"
|
||||
|
||||
#include "nsIGenericFactory.h"
|
||||
|
||||
// {0ffd3880-7a1a-11d6-a384-975d1d5f86fc}
|
||||
#define NS_SECURITYDIALOGS_CID \
|
||||
|
@ -55,6 +59,27 @@
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(SecurityDialogs);
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(CocoaPromptService);
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(KeychainPrompt);
|
||||
//NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadListener);
|
||||
|
||||
static NS_IMETHODIMP
|
||||
nsDownloadListenerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
*aResult = NULL;
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsDownloadListener* inst;
|
||||
NS_NEWXPCOM(inst, nsDownloadListener);
|
||||
if (!inst)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(inst);
|
||||
inst->SetDisplayFactory([ProgressDlgController sharedDownloadController]);
|
||||
nsresult rv = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// used by MainController to register the components in which we want to override
|
||||
// with the Gecko embed layer.
|
||||
|
@ -83,6 +108,12 @@ static const nsModuleComponentInfo gAppComponents[] = {
|
|||
NS_KEYCHAINPROMPT_CID,
|
||||
"@mozilla.org/wallet/single-sign-on-prompt;1",
|
||||
KeychainPromptConstructor
|
||||
},
|
||||
{
|
||||
"Download",
|
||||
NS_DOWNLOAD_CID,
|
||||
NS_DOWNLOAD_CONTRACTID,
|
||||
nsDownloadListenerConstructor
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -52,9 +52,8 @@
|
|||
{
|
||||
IBOutlet NSApplication* mApplication;
|
||||
|
||||
// The following two items are used by the filter list when saving files.
|
||||
// The following item is added to NSSavePanels as an accessory view
|
||||
IBOutlet NSView* mFilterView;
|
||||
IBOutlet NSPopUpButton* mFilterList;
|
||||
|
||||
// IBOutlet NSMenuItem* mOfflineMenuItem;
|
||||
IBOutlet NSMenuItem* mCloseWindowMenuItem;
|
||||
|
@ -137,11 +136,12 @@
|
|||
-(IBAction) addFolder:(id)aSender;
|
||||
-(IBAction) addSeparator:(id)aSender;
|
||||
|
||||
//Window menu actions
|
||||
// Window menu actions
|
||||
-(IBAction) newTab:(id)aSender;
|
||||
-(IBAction) closeTab:(id)aSender;
|
||||
-(IBAction) downloadsWindow:(id)aSender;
|
||||
|
||||
//Help menu actions
|
||||
// Help menu actions
|
||||
-(IBAction) infoLink:(id)aSender;
|
||||
-(IBAction) feedbackLink:(id)aSender;
|
||||
|
||||
|
@ -154,7 +154,8 @@
|
|||
|
||||
- (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost;
|
||||
|
||||
-(NSWindow*)getFrontmostBrowserWindow;
|
||||
- (NSView*)getSavePanelView;
|
||||
- (NSWindow*)getFrontmostBrowserWindow;
|
||||
|
||||
- (MVPreferencesController *)preferencesController;
|
||||
- (void)displayPreferencesWindow:sender;
|
||||
|
|
|
@ -260,19 +260,7 @@ const int kReuseWindowOnAE = 2;
|
|||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if ([ProgressDlgController numDownloadInProgress] > 0)
|
||||
{
|
||||
NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?");
|
||||
NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @"");
|
||||
NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel");
|
||||
NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit");
|
||||
// while the panel is up, download dialogs won't update (no timers firing) but
|
||||
// downloads continue (PLEvents being processed)
|
||||
if (NSRunAlertPanel(alert, message, okButton, altButton, nil) == NSAlertDefaultReturn)
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
return NSTerminateNow;
|
||||
return [[ProgressDlgController sharedDownloadController] allowTerminate];
|
||||
}
|
||||
|
||||
-(void)applicationWillTerminate: (NSNotification*)aNotification
|
||||
|
@ -439,7 +427,7 @@ const int kReuseWindowOnAE = 2;
|
|||
{
|
||||
BrowserWindowController* browserController = [self getMainWindowBrowserController];
|
||||
if (browserController)
|
||||
[browserController saveDocument:NO filterView:mFilterView filterList: mFilterList];
|
||||
[browserController saveDocument:NO filterView:mFilterView];
|
||||
}
|
||||
|
||||
-(IBAction) pageSetup:(id)aSender
|
||||
|
@ -584,6 +572,11 @@ const int kReuseWindowOnAE = 2;
|
|||
}
|
||||
}
|
||||
|
||||
-(IBAction) downloadsWindow:(id)aSender
|
||||
{
|
||||
[[ProgressDlgController sharedDownloadController] showWindow:aSender];
|
||||
}
|
||||
|
||||
- (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost;
|
||||
{
|
||||
[mAddBookmarkMenuItem setEnabled:inBrowserWindowFrontmost];
|
||||
|
@ -591,6 +584,11 @@ const int kReuseWindowOnAE = 2;
|
|||
[mCreateBookmarksSeparatorMenuItem setEnabled:NO]; // separators are not implemented yet
|
||||
}
|
||||
|
||||
- (NSView*)getSavePanelView
|
||||
{
|
||||
return mFilterView;
|
||||
}
|
||||
|
||||
-(NSWindow*)getFrontmostBrowserWindow
|
||||
{
|
||||
// for some reason, [NSApp mainWindow] doesn't always work, so we have to
|
||||
|
|
|
@ -47,7 +47,58 @@ NSGETMODULE(_name) (nsIComponentManager* aCompMgr, \
|
|||
}
|
||||
|
||||
// NSGetModule entry points
|
||||
DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsUCvJAModule) DECL_NSGETMODULE(nsUCvCnModule) DECL_NSGETMODULE(nsUCvLatinModule) DECL_NSGETMODULE(nsUCvTWModule) DECL_NSGETMODULE(nsUCvTW2Module) DECL_NSGETMODULE(nsUCvKoModule) DECL_NSGETMODULE(nsLocaleModule) DECL_NSGETMODULE(nsStringBundleModule) DECL_NSGETMODULE(nsLWBrkModule) DECL_NSGETMODULE(nsCharDetModule) DECL_NSGETMODULE(xpconnect) DECL_NSGETMODULE(cacheservice) DECL_NSGETMODULE(necko_core_and_primary_protocols) DECL_NSGETMODULE(necko_secondary_protocols) DECL_NSGETMODULE(nsURILoaderModule) DECL_NSGETMODULE(nsPrefModule) DECL_NSGETMODULE(nsCJVMManagerModule) DECL_NSGETMODULE(nsSecurityManagerModule) DECL_NSGETMODULE(nsChromeModule) DECL_NSGETMODULE(nsRDFModule) DECL_NSGETMODULE(nsParserModule) DECL_NSGETMODULE(nsGfxMacModule) DECL_NSGETMODULE(nsGfx2Module) DECL_NSGETMODULE(nsImageLib2Module) DECL_NSGETMODULE(nsPNGDecoderModule) DECL_NSGETMODULE(nsGIFModule2) DECL_NSGETMODULE(nsJPEGDecoderModule) DECL_NSGETMODULE(nsPluginModule) DECL_NSGETMODULE(javascript__protocol) DECL_NSGETMODULE(DOM_components) DECL_NSGETMODULE(nsViewModule) DECL_NSGETMODULE(nsWidgetMacModule) DECL_NSGETMODULE(nsContentModule) DECL_NSGETMODULE(nsLayoutModule) DECL_NSGETMODULE(nsMorkModule) DECL_NSGETMODULE(docshell_provider) DECL_NSGETMODULE(embedcomponents) DECL_NSGETMODULE(Browser_Embedding_Module) DECL_NSGETMODULE(nsEditorModule) DECL_NSGETMODULE(nsTransactionManagerModule) DECL_NSGETMODULE(nsTextServicesModule) DECL_NSGETMODULE(nsProfileModule) DECL_NSGETMODULE(Session_History_Module) DECL_NSGETMODULE(application) DECL_NSGETMODULE(nsCookieModule) DECL_NSGETMODULE(nsXMLExtrasModule) DECL_NSGETMODULE(nsUniversalCharDetModule) DECL_NSGETMODULE(BOOT) DECL_NSGETMODULE(NSS)
|
||||
DECL_NSGETMODULE(UcharUtil)
|
||||
DECL_NSGETMODULE(nsUConvModule)
|
||||
DECL_NSGETMODULE(nsUCvJAModule)
|
||||
DECL_NSGETMODULE(nsUCvCnModule)
|
||||
DECL_NSGETMODULE(nsUCvLatinModule)
|
||||
DECL_NSGETMODULE(nsUCvTWModule)
|
||||
DECL_NSGETMODULE(nsUCvTW2Module)
|
||||
DECL_NSGETMODULE(nsUCvKoModule)
|
||||
DECL_NSGETMODULE(nsLocaleModule)
|
||||
DECL_NSGETMODULE(nsStringBundleModule)
|
||||
DECL_NSGETMODULE(nsLWBrkModule)
|
||||
DECL_NSGETMODULE(nsCharDetModule)
|
||||
DECL_NSGETMODULE(xpconnect)
|
||||
DECL_NSGETMODULE(cacheservice)
|
||||
DECL_NSGETMODULE(necko_core_and_primary_protocols)
|
||||
DECL_NSGETMODULE(necko_secondary_protocols)
|
||||
DECL_NSGETMODULE(nsURILoaderModule)
|
||||
DECL_NSGETMODULE(nsPrefModule)
|
||||
DECL_NSGETMODULE(nsCJVMManagerModule)
|
||||
DECL_NSGETMODULE(nsSecurityManagerModule)
|
||||
DECL_NSGETMODULE(nsChromeModule)
|
||||
DECL_NSGETMODULE(nsRDFModule)
|
||||
DECL_NSGETMODULE(nsParserModule)
|
||||
DECL_NSGETMODULE(nsGfxMacModule)
|
||||
DECL_NSGETMODULE(nsGfx2Module)
|
||||
DECL_NSGETMODULE(nsImageLib2Module)
|
||||
DECL_NSGETMODULE(nsPNGDecoderModule)
|
||||
DECL_NSGETMODULE(nsGIFModule2)
|
||||
DECL_NSGETMODULE(nsJPEGDecoderModule)
|
||||
DECL_NSGETMODULE(nsPluginModule)
|
||||
DECL_NSGETMODULE(javascript__protocol)
|
||||
DECL_NSGETMODULE(JS_component_loader)
|
||||
DECL_NSGETMODULE(DOM_components)
|
||||
DECL_NSGETMODULE(nsViewModule)
|
||||
DECL_NSGETMODULE(nsWidgetMacModule)
|
||||
DECL_NSGETMODULE(nsContentModule)
|
||||
DECL_NSGETMODULE(nsLayoutModule)
|
||||
DECL_NSGETMODULE(nsMorkModule)
|
||||
DECL_NSGETMODULE(docshell_provider)
|
||||
DECL_NSGETMODULE(embedcomponents)
|
||||
DECL_NSGETMODULE(Browser_Embedding_Module)
|
||||
DECL_NSGETMODULE(nsEditorModule)
|
||||
DECL_NSGETMODULE(nsTransactionManagerModule)
|
||||
DECL_NSGETMODULE(nsTextServicesModule)
|
||||
DECL_NSGETMODULE(nsProfileModule)
|
||||
DECL_NSGETMODULE(Session_History_Module)
|
||||
DECL_NSGETMODULE(application)
|
||||
DECL_NSGETMODULE(nsCookieModule)
|
||||
DECL_NSGETMODULE(nsXMLExtrasModule)
|
||||
DECL_NSGETMODULE(nsUniversalCharDetModule)
|
||||
DECL_NSGETMODULE(BOOT)
|
||||
DECL_NSGETMODULE(NSS)
|
||||
#line 52 "nsStaticComponents.cpp.in"
|
||||
|
||||
/**
|
||||
|
@ -55,7 +106,58 @@ DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsU
|
|||
*/
|
||||
static nsStaticModuleInfo gStaticModuleInfo[] = {
|
||||
#define MODULE(_name) { (#_name), NSGETMODULE(_name) }
|
||||
MODULE(UcharUtil), MODULE(nsUConvModule), MODULE(nsUCvJAModule), MODULE(nsUCvCnModule), MODULE(nsUCvLatinModule), MODULE(nsUCvTWModule), MODULE(nsUCvTW2Module), MODULE(nsUCvKoModule), MODULE(nsLocaleModule), MODULE(nsStringBundleModule), MODULE(nsLWBrkModule), MODULE(nsCharDetModule), MODULE(xpconnect), MODULE(cacheservice), MODULE(necko_core_and_primary_protocols), MODULE(necko_secondary_protocols), MODULE(nsURILoaderModule), MODULE(nsPrefModule), MODULE(nsCJVMManagerModule), MODULE(nsSecurityManagerModule), MODULE(nsChromeModule), MODULE(nsRDFModule), MODULE(nsParserModule), MODULE(nsGfxMacModule), MODULE(nsGfx2Module), MODULE(nsImageLib2Module), MODULE(nsPNGDecoderModule), MODULE(nsGIFModule2), MODULE(nsJPEGDecoderModule), MODULE(nsPluginModule), MODULE(javascript__protocol), MODULE(DOM_components), MODULE(nsViewModule), MODULE(nsWidgetMacModule), MODULE(nsContentModule), MODULE(nsLayoutModule), MODULE(nsMorkModule), MODULE(docshell_provider), MODULE(embedcomponents), MODULE(Browser_Embedding_Module), MODULE(nsEditorModule), MODULE(nsTransactionManagerModule), MODULE(nsTextServicesModule), MODULE(nsProfileModule), MODULE(Session_History_Module), MODULE(application), MODULE(nsCookieModule), MODULE(nsXMLExtrasModule), MODULE(nsUniversalCharDetModule), MODULE(BOOT), MODULE(NSS),
|
||||
MODULE(UcharUtil),
|
||||
MODULE(nsUConvModule),
|
||||
MODULE(nsUCvJAModule),
|
||||
MODULE(nsUCvCnModule),
|
||||
MODULE(nsUCvLatinModule),
|
||||
MODULE(nsUCvTWModule),
|
||||
MODULE(nsUCvTW2Module),
|
||||
MODULE(nsUCvKoModule),
|
||||
MODULE(nsLocaleModule),
|
||||
MODULE(nsStringBundleModule),
|
||||
MODULE(nsLWBrkModule),
|
||||
MODULE(nsCharDetModule),
|
||||
MODULE(xpconnect),
|
||||
MODULE(cacheservice),
|
||||
MODULE(necko_core_and_primary_protocols),
|
||||
MODULE(necko_secondary_protocols),
|
||||
MODULE(nsURILoaderModule),
|
||||
MODULE(nsPrefModule),
|
||||
MODULE(nsCJVMManagerModule),
|
||||
MODULE(nsSecurityManagerModule),
|
||||
MODULE(nsChromeModule),
|
||||
MODULE(nsRDFModule),
|
||||
MODULE(nsParserModule),
|
||||
MODULE(nsGfxMacModule),
|
||||
MODULE(nsGfx2Module),
|
||||
MODULE(nsImageLib2Module),
|
||||
MODULE(nsPNGDecoderModule),
|
||||
MODULE(nsGIFModule2),
|
||||
MODULE(nsJPEGDecoderModule),
|
||||
MODULE(nsPluginModule),
|
||||
MODULE(javascript__protocol),
|
||||
MODULE(JS_component_loader),
|
||||
MODULE(DOM_components),
|
||||
MODULE(nsViewModule),
|
||||
MODULE(nsWidgetMacModule),
|
||||
MODULE(nsContentModule),
|
||||
MODULE(nsLayoutModule),
|
||||
MODULE(nsMorkModule),
|
||||
MODULE(docshell_provider),
|
||||
MODULE(embedcomponents),
|
||||
MODULE(Browser_Embedding_Module),
|
||||
MODULE(nsEditorModule),
|
||||
MODULE(nsTransactionManagerModule),
|
||||
MODULE(nsTextServicesModule),
|
||||
MODULE(nsProfileModule),
|
||||
MODULE(Session_History_Module),
|
||||
MODULE(application),
|
||||
MODULE(nsCookieModule),
|
||||
MODULE(nsXMLExtrasModule),
|
||||
MODULE(nsUniversalCharDetModule),
|
||||
MODULE(BOOT),
|
||||
MODULE(NSS),
|
||||
#line 60 "nsStaticComponents.cpp.in"
|
||||
};
|
||||
|
||||
|
|
|
@ -601,7 +601,7 @@ const int kBookmarksRootItemTag = -2;
|
|||
|
||||
//Set cell's textual contents
|
||||
//[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString: nameAttr]];
|
||||
cellValue = [[NSMutableAttributedString alloc] initWithString:[NSString stringWith_nsAString: nameAttr]];
|
||||
cellValue = [[[NSMutableAttributedString alloc] initWithString:[NSString stringWith_nsAString: nameAttr]] autorelease];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
NSMutableAttributedString* attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment];
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
// see http://developer.apple.com/qa/qa2001/qa1117.html
|
||||
if ( ([self tabViewType] == NSNoTabsBezelBorder) && (NSAppKitVersionNumber < 633) )
|
||||
return NO;
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ static const int kEscapeKeyCode = 53;
|
|||
BOOL madeFirstResponder = [super makeFirstResponder:responder];
|
||||
if (madeFirstResponder && oldResponder != [self firstResponder])
|
||||
[(BrowserWindowController*)[self delegate] focusChangedFrom:oldResponder to:[self firstResponder]];
|
||||
|
||||
//NSLog(@"Old FR %@, new FR %@, responder %@, made %d", oldResponder, [self firstResponder], responder, madeFirstResponder);
|
||||
return madeFirstResponder;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,12 +109,12 @@ typedef enum
|
|||
IBOutlet NSTextField* mLocationSheetURLField;
|
||||
IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock
|
||||
IBOutlet PageProxyIcon* mProxyIcon;
|
||||
IBOutlet BrowserContentView* mContentView;
|
||||
IBOutlet BrowserContentView* mContentView;
|
||||
|
||||
IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource;
|
||||
IBOutlet HistoryDataSource* mHistoryDataSource;
|
||||
IBOutlet HistoryDataSource* mHistoryDataSource;
|
||||
|
||||
IBOutlet BookmarksToolbar* mPersonalToolbar;
|
||||
IBOutlet BookmarksToolbar* mPersonalToolbar;
|
||||
|
||||
IBOutlet NSWindow* mAddBookmarkSheetWindow;
|
||||
IBOutlet NSTextField* mAddBookmarkTitleField;
|
||||
|
@ -191,6 +191,8 @@ typedef enum
|
|||
- (void)updateLocationFields:(NSString *)locationString;
|
||||
- (void)updateSiteIcons:(NSImage *)siteIconImage;
|
||||
- (void)updateToolbarItems;
|
||||
- (void)loadingStarted;
|
||||
- (void)loadingDone;
|
||||
- (void)focusURLBar;
|
||||
|
||||
// call to update the image of the lock icon with a value from nsIWebProgressListener
|
||||
|
@ -211,9 +213,9 @@ typedef enum
|
|||
- (IBAction)viewSource:(id)aSender; // focussed frame or page
|
||||
- (IBAction)viewPageSource:(id)aSender; // top-level page
|
||||
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList;
|
||||
- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename;
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView;
|
||||
- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename;
|
||||
|
||||
- (IBAction)printDocument:(id)aSender;
|
||||
- (IBAction)pageSetup:(id)aSender;
|
||||
- (IBAction)performSearch:(id)aSender;
|
||||
|
@ -302,6 +304,7 @@ typedef enum
|
|||
- (IBAction)bookmarkLink: (id)aSender;
|
||||
|
||||
- (IBAction)copyLinkLocation:(id)aSender;
|
||||
- (IBAction)copyImage:(id)sender;
|
||||
- (IBAction)copyImageLocation:(id)sender;
|
||||
|
||||
- (BookmarksToolbar*) bookmarksToolbar;
|
||||
|
|
|
@ -816,6 +816,19 @@ static NSArray* sToolbarDefaults = nil;
|
|||
else
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)loadingStarted
|
||||
{
|
||||
[self updateToolbarItems];
|
||||
[self startThrobber];
|
||||
}
|
||||
|
||||
- (void)loadingDone
|
||||
{
|
||||
[self updateToolbarItems];
|
||||
[self stopThrobber];
|
||||
[mHistoryDataSource refresh];
|
||||
}
|
||||
|
||||
- (void)updateToolbarItems
|
||||
{
|
||||
|
@ -960,16 +973,14 @@ static NSArray* sToolbarDefaults = nil;
|
|||
}
|
||||
}
|
||||
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView
|
||||
{
|
||||
[[mBrowserView getBrowserView] saveDocument:focusedFrame filterView:aFilterView filterList:aFilterList];
|
||||
[[mBrowserView getBrowserView] saveDocument:focusedFrame filterView:aFilterView];
|
||||
}
|
||||
|
||||
- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename
|
||||
- (void)saveURL: (NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename
|
||||
{
|
||||
[[mBrowserView getBrowserView] saveURL: aFilterView filterList: aFilterList
|
||||
url: aURLSpec suggestedFilename: aFilename];
|
||||
[[mBrowserView getBrowserView] saveURL: aFilterView url: aURLSpec suggestedFilename: aFilename];
|
||||
}
|
||||
|
||||
- (void)loadSourceOfURL:(NSString*)urlStr
|
||||
|
@ -1890,12 +1901,14 @@ static NSArray* sToolbarDefaults = nil;
|
|||
|
||||
- (IBAction)savePageAs:(id)aSender
|
||||
{
|
||||
[self saveDocument:NO filterView:nil filterList: nil];
|
||||
NSView* accessoryView = [[NSApp delegate] getSavePanelView];
|
||||
[self saveDocument:NO filterView:accessoryView];
|
||||
}
|
||||
|
||||
- (IBAction)saveFrameAs:(id)aSender
|
||||
{
|
||||
[self saveDocument:YES filterView:nil filterList: nil];
|
||||
NSView* accessoryView = [[NSApp delegate] getSavePanelView];
|
||||
[self saveDocument:YES filterView:accessoryView];
|
||||
}
|
||||
|
||||
- (IBAction)saveLinkAs:(id)aSender
|
||||
|
@ -1915,8 +1928,7 @@ static NSArray* sToolbarDefaults = nil;
|
|||
nsAutoString text;
|
||||
GeckoUtils::GatherTextUnder(mContextMenuNode, text);
|
||||
|
||||
[self saveURL: nil filterList: nil
|
||||
url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]];
|
||||
[self saveURL:nil url:hrefStr suggestedFilename:[NSString stringWith_nsAString:text]];
|
||||
}
|
||||
|
||||
- (IBAction)saveImageAs:(id)aSender
|
||||
|
@ -1931,11 +1943,18 @@ static NSArray* sToolbarDefaults = nil;
|
|||
|
||||
NSString* hrefStr = [NSString stringWith_nsAString: url];
|
||||
|
||||
[self saveURL: nil filterList: nil
|
||||
url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]];
|
||||
[self saveURL:nil url:hrefStr suggestedFilename: [NSString stringWith_nsAString: text]];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)copyImage:(id)sender
|
||||
{
|
||||
nsCOMPtr<nsIWebBrowser> webBrowser = getter_AddRefs([[[self getBrowserWrapper] getBrowserView] getWebBrowser]);
|
||||
nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(webBrowser));
|
||||
if (clipboard)
|
||||
clipboard->CopyImageContents();
|
||||
}
|
||||
|
||||
- (IBAction)copyImageLocation:(id)sender
|
||||
{
|
||||
nsCOMPtr<nsIWebBrowser> webBrowser = getter_AddRefs([[[self getBrowserWrapper] getBrowserView] getWebBrowser]);
|
||||
|
|
|
@ -335,10 +335,8 @@ const NSString* kOfflineNotificationName = @"offlineModeChanged";
|
|||
mTabTitle = [mLoadingStatusString retain];
|
||||
[mTabItem setLabel:mTabTitle];
|
||||
|
||||
if (mWindowController) {
|
||||
[mWindowController updateToolbarItems];
|
||||
[mWindowController startThrobber];
|
||||
}
|
||||
if (mWindowController)
|
||||
[mWindowController loadingStarted];
|
||||
}
|
||||
|
||||
- (void)onLoadingCompleted:(BOOL)succeeded
|
||||
|
@ -402,10 +400,8 @@ const NSString* kOfflineNotificationName = @"offlineModeChanged";
|
|||
[self removeFromSuperview];
|
||||
}
|
||||
|
||||
if (mWindowController) {
|
||||
[mWindowController updateToolbarItems];
|
||||
[mWindowController stopThrobber];
|
||||
}
|
||||
if (mWindowController)
|
||||
[mWindowController loadingDone];
|
||||
}
|
||||
|
||||
- (void)onProgressChange:(int)currentBytes outOf:(int)maxBytes
|
||||
|
|
|
@ -139,8 +139,7 @@ ContentClickListener::MouseClick(nsIDOMEvent* aEvent)
|
|||
nsAutoString text;
|
||||
GeckoUtils::GatherTextUnder(content, text);
|
||||
|
||||
[mBrowserController saveURL: nil filterList: nil
|
||||
url: hrefStr suggestedFilename: [NSString stringWith_nsAString: text]];
|
||||
[mBrowserController saveURL:nil url:hrefStr suggestedFilename:[NSString stringWith_nsAString:text]];
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -51,10 +51,16 @@
|
|||
|
||||
class nsIPrefBranch;
|
||||
|
||||
enum KeychainPromptResult { kSave, kDontRemember, kNeverRemember } ;
|
||||
|
||||
@class CHBrowserView;
|
||||
|
||||
|
||||
@interface KeychainService : NSObject
|
||||
{
|
||||
IBOutlet id confirmStorePasswordPanel;
|
||||
IBOutlet id confirmChangePasswordPanel;
|
||||
|
||||
BOOL mIsEnabled;
|
||||
BOOL mIsAutoFillEnabled;
|
||||
|
||||
|
@ -64,6 +70,13 @@ class nsIPrefBranch;
|
|||
+ (KeychainService*) instance;
|
||||
- (void) shutdown:(id)sender;
|
||||
|
||||
- (IBAction)hitButtonOK:(id)sender;
|
||||
- (IBAction)hitButtonCancel:(id)sender;
|
||||
- (IBAction)hitButtonOther:(id)sender;
|
||||
|
||||
- (KeychainPromptResult)confirmStorePassword:(NSWindow*)parent;
|
||||
- (BOOL)confirmChangedPassword:(NSWindow*)parent;
|
||||
|
||||
- (BOOL) getUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSMutableString*)username password:(NSMutableString*)pwd item:(KCItemRef*)outItem;
|
||||
- (BOOL) findUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort;
|
||||
- (void) storeUsernameAndPassword:(NSString*)realm port:(PRInt32)inPort user:(NSString*)username password:(NSString*)pwd;
|
||||
|
@ -75,13 +88,43 @@ class nsIPrefBranch;
|
|||
- (BOOL) isEnabled;
|
||||
- (BOOL) isAutoFillEnabled;
|
||||
|
||||
// routines to manipulate the keychain deny list for which hosts we shouldn't
|
||||
// ask about
|
||||
- (void) addHostToDenyList:(NSString*)host;
|
||||
- (BOOL) isHostInDenyList:(NSString*)host;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
//
|
||||
// KeychainDenyList
|
||||
//
|
||||
// A singleton object that maintains a list of sites where we should
|
||||
// not prompt the user for saving in the keychain. This object also
|
||||
// handles archiving the list in the user's profile dir.
|
||||
//
|
||||
|
||||
@interface KeychainDenyList : NSObject
|
||||
{
|
||||
NSMutableArray* mDenyList; // the list
|
||||
BOOL mIsDirty; // do we need to write the list to disk?
|
||||
}
|
||||
|
||||
+ (KeychainDenyList*) instance;
|
||||
- (void) shutdown:(id)sender;
|
||||
|
||||
- (BOOL) isHostPresent:(NSString*)host;
|
||||
- (void) addHost:(NSString*)host;
|
||||
- (void) removeHost:(NSString*)host;
|
||||
- (void) writeToDisk;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
class KeychainPrompt : public nsIAuthPromptWrapper
|
||||
{
|
||||
public:
|
||||
KeychainPrompt();
|
||||
KeychainPrompt(KeychainService*);
|
||||
virtual ~KeychainPrompt();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -95,7 +138,6 @@ protected:
|
|||
static void ExtractHostAndPort(const PRUnichar* inRealm, NSString** outHost, PRInt32* outPort);
|
||||
|
||||
nsCOMPtr<nsIPrompt> mPrompt;
|
||||
KeychainService* mKeychain;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -105,7 +147,7 @@ class KeychainFormSubmitObserver : public nsIObserver,
|
|||
public nsIFormSubmitObserver
|
||||
{
|
||||
public:
|
||||
KeychainFormSubmitObserver(KeychainService*);
|
||||
KeychainFormSubmitObserver();
|
||||
virtual ~KeychainFormSubmitObserver();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -116,12 +158,10 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
static BOOL CheckStorePasswordYN(nsIDOMWindowInternal*);
|
||||
static KeychainPromptResult CheckStorePasswordYN(nsIDOMWindowInternal*);
|
||||
static BOOL CheckChangeDataYN(nsIDOMWindowInternal*);
|
||||
|
||||
static NSWindow* GetNSWindow(nsIDOMWindowInternal* inWindow);
|
||||
|
||||
KeychainService* mKeychain;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -129,11 +169,10 @@ private:
|
|||
//
|
||||
@interface KeychainBrowserListener : NSObject<CHBrowserListener>
|
||||
{
|
||||
KeychainService* mKeychain;
|
||||
CHBrowserView* mBrowserView;
|
||||
}
|
||||
|
||||
- (id)initWithBrowser:(KeychainService*)keychain browser:(CHBrowserView*)aBrowser;
|
||||
- (id)initWithBrowser:(CHBrowserView*)aBrowser;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@
|
|||
#include "nsIWindowWatcher.h"
|
||||
#include "nsIWebBrowserChrome.h"
|
||||
#include "nsIEmbeddingSiteWindow.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
extern NSString* XPCOMShutDownNotificationName;
|
||||
|
||||
|
||||
nsresult
|
||||
|
@ -114,7 +117,7 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused)
|
|||
// observer service uses a weakref.
|
||||
nsCOMPtr<nsIObserverService> svc = do_GetService("@mozilla.org/observer-service;1");
|
||||
NS_ASSERTION(svc, "Keychain can't get observer service");
|
||||
mFormSubmitObserver = new KeychainFormSubmitObserver(self);
|
||||
mFormSubmitObserver = new KeychainFormSubmitObserver();
|
||||
if ( mFormSubmitObserver && svc ) {
|
||||
NS_ADDREF(mFormSubmitObserver);
|
||||
svc->AddObserver(mFormSubmitObserver, NS_FORMSUBMIT_SUBJECT, PR_FALSE);
|
||||
|
@ -122,7 +125,7 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused)
|
|||
|
||||
// register for the cocoa notification posted when XPCOM shutdown so we
|
||||
// can unregister the pref callbacks we register below
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:@"XPCOM Shutdown"
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:XPCOMShutDownNotificationName
|
||||
object:nil];
|
||||
|
||||
// cache the values of the prefs and register pref-changed callbacks. Yeah, I know
|
||||
|
@ -139,6 +142,10 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused)
|
|||
pref->RegisterCallback(gAutoFillEnabledPref, KeychainPrefChangedCallback, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
// load the keychain.nib file with our dialogs in it
|
||||
BOOL success = [NSBundle loadNibNamed:@"Keychain" owner:self];
|
||||
NS_ASSERTION(success, "can't load keychain prompt dialogs");
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -168,6 +175,8 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused)
|
|||
pref->UnregisterCallback(gUseKeychainPref, KeychainPrefChangedCallback, nsnull);
|
||||
pref->UnregisterCallback(gAutoFillEnabledPref, KeychainPrefChangedCallback, nsnull);
|
||||
}
|
||||
|
||||
[sInstance release];
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,7 +333,181 @@ int KeychainPrefChangedCallback(const char* inPref, void* unused)
|
|||
//
|
||||
- (void) addListenerToView:(CHBrowserView*)view
|
||||
{
|
||||
[view addListener:[[[KeychainBrowserListener alloc] initWithBrowser:self browser:view] autorelease]];
|
||||
[view addListener:[[[KeychainBrowserListener alloc] initWithBrowser:view] autorelease]];
|
||||
}
|
||||
|
||||
//
|
||||
// hitButtonOK:
|
||||
// hitButtonCancel:
|
||||
// hitButtonOther:
|
||||
//
|
||||
// actions for the buttons of the keychain prompt dialogs.
|
||||
//
|
||||
|
||||
enum { kOKButton = 0, kCancelButton = 1, kOtherButton = 2 };
|
||||
|
||||
- (IBAction)hitButtonOK:(id)sender
|
||||
{
|
||||
[NSApp stopModalWithCode:kOKButton];
|
||||
}
|
||||
|
||||
- (IBAction)hitButtonCancel:(id)sender
|
||||
{
|
||||
[NSApp stopModalWithCode:kCancelButton];
|
||||
}
|
||||
|
||||
- (IBAction)hitButtonOther:(id)sender
|
||||
{
|
||||
[NSApp stopModalWithCode:kOtherButton];
|
||||
}
|
||||
|
||||
//
|
||||
// confirmStorePassword:
|
||||
//
|
||||
// Puts up a dialog when the keychain doesn't yet have an entry from
|
||||
// this site asking to store it, forget it this once, or mark the site
|
||||
// on a deny list so we never ask again.
|
||||
//
|
||||
- (KeychainPromptResult)confirmStorePassword:(NSWindow*)parent
|
||||
{
|
||||
int result = [NSApp runModalForWindow:confirmStorePasswordPanel relativeToWindow:parent];
|
||||
[confirmStorePasswordPanel close];
|
||||
|
||||
// the results of hitButtonXX: map to the corresponding values in the
|
||||
// |KeychainPromptResult| enum so we can just cast and return
|
||||
return NS_STATIC_CAST(KeychainPromptResult, result);
|
||||
}
|
||||
|
||||
//
|
||||
// confirmChangedPassword:
|
||||
//
|
||||
// The password stored in the keychain differs from what the user typed
|
||||
// in. Ask what they want to do to resolve the issue.
|
||||
//
|
||||
- (BOOL)confirmChangedPassword:(NSWindow*)parent
|
||||
{
|
||||
int result = [NSApp runModalForWindow:confirmChangePasswordPanel relativeToWindow:parent];
|
||||
[confirmChangePasswordPanel close];
|
||||
return (result == kOKButton);
|
||||
}
|
||||
|
||||
|
||||
- (void) addHostToDenyList:(NSString*)host
|
||||
{
|
||||
[[KeychainDenyList instance] addHost:host];
|
||||
}
|
||||
|
||||
- (BOOL) isHostInDenyList:(NSString*)host
|
||||
{
|
||||
return [[KeychainDenyList instance] isHostPresent:host];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface KeychainDenyList (KeychainDenyListPrivate)
|
||||
- (NSString*) pathToDenyListFile;
|
||||
@end
|
||||
|
||||
|
||||
@implementation KeychainDenyList
|
||||
|
||||
static KeychainDenyList *sDenyListInstance = nil;
|
||||
|
||||
+ (KeychainDenyList*) instance
|
||||
{
|
||||
return sDenyListInstance ? sDenyListInstance : sDenyListInstance = [[self alloc] init];
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ( (self = [super init]) ) {
|
||||
mDenyList = [[NSUnarchiver unarchiveObjectWithFile:[self pathToDenyListFile]] retain];
|
||||
if ( !mDenyList )
|
||||
mDenyList = [[NSMutableArray alloc] init];
|
||||
|
||||
mIsDirty = NO;
|
||||
|
||||
// register for the cocoa notification posted when XPCOM shutdown so we
|
||||
// can release our singleton and flush the file
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shutdown:) name:XPCOMShutDownNotificationName object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self writeToDisk];
|
||||
[mDenyList release];
|
||||
}
|
||||
|
||||
//
|
||||
// shutdown:
|
||||
//
|
||||
// Called in response to the cocoa notification "XPCOM Shutdown" sent by the cocoa
|
||||
// browser service before it terminates embedding and shuts down xpcom. Allows us
|
||||
// to get rid of anything we're holding onto for the length of the app.
|
||||
//
|
||||
- (void) shutdown:(id)unused
|
||||
{
|
||||
[sDenyListInstance release];
|
||||
}
|
||||
|
||||
//
|
||||
// writeToDisk
|
||||
//
|
||||
// flushes the deny list to the save file in the user's profile, but only
|
||||
// if it has changed since we read it in.
|
||||
//
|
||||
- (void) writeToDisk
|
||||
{
|
||||
if ( mIsDirty )
|
||||
[NSArchiver archiveRootObject:mDenyList toFile:[self pathToDenyListFile]];
|
||||
mIsDirty = NO;
|
||||
}
|
||||
|
||||
- (BOOL) isHostPresent:(NSString*)host
|
||||
{
|
||||
return [mDenyList containsObject:host];
|
||||
}
|
||||
|
||||
- (void) addHost:(NSString*)host
|
||||
{
|
||||
if ( ![self isHostPresent:host] ) {
|
||||
[mDenyList addObject:host];
|
||||
mIsDirty = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) removeHost:(NSString*)host
|
||||
{
|
||||
if ( [self isHostPresent:host] ) {
|
||||
[mDenyList removeObject:host];
|
||||
mIsDirty = YES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// pathToDenyListFile
|
||||
//
|
||||
// returns a path ('/' delimited) that cocoa can use to point to the
|
||||
// deny list save file in the current user's profile
|
||||
//
|
||||
- (NSString*) pathToDenyListFile
|
||||
{
|
||||
NSMutableString* path = [[[NSMutableString alloc] init] autorelease];
|
||||
|
||||
nsCOMPtr<nsIFile> appProfileDir;
|
||||
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(appProfileDir));
|
||||
if ( appProfileDir ) {
|
||||
nsAutoString profilePath;
|
||||
appProfileDir->GetPath(profilePath);
|
||||
[path setString:[NSString stringWith_nsAString:profilePath]];
|
||||
[path appendString:@"/Keychain Deny List"]; // |profilePath| is '/' delimited
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -338,12 +521,6 @@ NS_IMPL_ISUPPORTS2(KeychainPrompt,
|
|||
nsIAuthPromptWrapper)
|
||||
|
||||
KeychainPrompt::KeychainPrompt()
|
||||
: mKeychain([KeychainService instance])
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
KeychainPrompt::KeychainPrompt(KeychainService* keychain) : mKeychain(keychain)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
@ -391,7 +568,8 @@ KeychainPrompt::ExtractHostAndPort(const PRUnichar* inRealm, NSString** outHost,
|
|||
void
|
||||
KeychainPrompt::PreFill(const PRUnichar *realm, PRUnichar **user, PRUnichar **pwd)
|
||||
{
|
||||
if(![mKeychain isEnabled] || ![mKeychain isAutoFillEnabled])
|
||||
KeychainService* keychain = [KeychainService instance];
|
||||
if(![keychain isEnabled] || ![keychain isAutoFillEnabled])
|
||||
return;
|
||||
|
||||
NSString* host = nil;
|
||||
|
@ -409,7 +587,7 @@ KeychainPrompt::PreFill(const PRUnichar *realm, PRUnichar **user, PRUnichar **pw
|
|||
// Pre-fill user/password if found in the keychain.
|
||||
//
|
||||
KCItemRef ignore;
|
||||
if([mKeychain getUsernameAndPassword:(NSString*)host port:port user:username password:password item:&ignore]) {
|
||||
if([keychain getUsernameAndPassword:(NSString*)host port:port user:username password:password item:&ignore]) {
|
||||
if ( user )
|
||||
*user = [username createNewUnicodeBuffer];
|
||||
if ( pwd )
|
||||
|
@ -427,10 +605,12 @@ KeychainPrompt::ProcessPrompt(const PRUnichar* realm, bool checked, PRUnichar* u
|
|||
NSString* username = [NSString stringWithPRUnichars:user];
|
||||
NSString* password = [NSString stringWithPRUnichars:pwd];
|
||||
|
||||
KeychainService* keychain = [KeychainService instance];
|
||||
|
||||
NSMutableString* origUsername = [NSMutableString string];
|
||||
NSMutableString* origPwd = [NSMutableString string];
|
||||
KCItemRef itemRef;
|
||||
bool found = [mKeychain getUsernameAndPassword:(NSString*)host port:port user:origUsername password:origPwd item:&itemRef];
|
||||
bool found = [keychain getUsernameAndPassword:(NSString*)host port:port user:origUsername password:origPwd item:&itemRef];
|
||||
|
||||
//
|
||||
// Update, store or remove the user/password depending on the user
|
||||
|
@ -438,11 +618,11 @@ KeychainPrompt::ProcessPrompt(const PRUnichar* realm, bool checked, PRUnichar* u
|
|||
// keychain.
|
||||
//
|
||||
if(checked && !found)
|
||||
[mKeychain storeUsernameAndPassword:(NSString*)host port:port user:username password:password];
|
||||
[keychain storeUsernameAndPassword:(NSString*)host port:port user:username password:password];
|
||||
else if(checked && found && (![origUsername isEqualToString:username] || ![origPwd isEqualToString:password]))
|
||||
[mKeychain updateUsernameAndPassword:(NSString*)host port:port user:username password:password item:itemRef];
|
||||
[keychain updateUsernameAndPassword:(NSString*)host port:port user:username password:password item:itemRef];
|
||||
else if(!checked && found)
|
||||
[mKeychain removeUsernameAndPassword:(NSString*)host port:port item:itemRef];
|
||||
[keychain removeUsernameAndPassword:(NSString*)host port:port item:itemRef];
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -476,7 +656,7 @@ KeychainPrompt::PromptUsernameAndPassword(const PRUnichar *dialogTitle,
|
|||
{
|
||||
PreFill(realm, user, pwd);
|
||||
|
||||
PRBool checked = [mKeychain isEnabled];
|
||||
PRBool checked = [[KeychainService instance] isEnabled];
|
||||
PRUnichar* checkTitle = [NSLocalizedString(@"KeychainCheckTitle", @"") createNewUnicodeBuffer];
|
||||
|
||||
nsresult rv = mPrompt->PromptUsernameAndPassword(dialogTitle, text, user, pwd, checkTitle, &checked, _retval);
|
||||
|
@ -501,7 +681,7 @@ KeychainPrompt::PromptPassword(const PRUnichar *dialogTitle,
|
|||
{
|
||||
PreFill(realm, nsnull, pwd);
|
||||
|
||||
PRBool checked = [mKeychain isEnabled];
|
||||
PRBool checked = [[KeychainService instance] isEnabled];
|
||||
PRUnichar* checkTitle = [NSLocalizedString(@"KeychainCheckTitle", @"") createNewUnicodeBuffer];
|
||||
|
||||
nsresult rv = mPrompt->PromptPassword(dialogTitle, text, pwd, checkTitle, &checked, _retval);
|
||||
|
@ -530,7 +710,7 @@ NS_IMPL_ISUPPORTS2(KeychainFormSubmitObserver,
|
|||
nsIObserver,
|
||||
nsIFormSubmitObserver)
|
||||
|
||||
KeychainFormSubmitObserver::KeychainFormSubmitObserver(KeychainService* keychain) : mKeychain(keychain)
|
||||
KeychainFormSubmitObserver::KeychainFormSubmitObserver()
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
//NSLog(@"Keychain form submit observer created.");
|
||||
|
@ -551,7 +731,8 @@ NS_IMETHODIMP
|
|||
KeychainFormSubmitObserver::Notify(nsIContent* node, nsIDOMWindowInternal* window, nsIURI* actionURL,
|
||||
PRBool* cancelSubmit)
|
||||
{
|
||||
if (![mKeychain isEnabled])
|
||||
KeychainService* keychain = [KeychainService instance];
|
||||
if (![keychain isEnabled])
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLFormElement> formNode(do_QueryInterface(node));
|
||||
|
@ -590,25 +771,41 @@ KeychainFormSubmitObserver::Notify(nsIContent* node, nsIDOMWindowInternal* windo
|
|||
docURL->GetHost(host);
|
||||
docURL->GetPort(&port);
|
||||
|
||||
// is the host in the deny list? if yes, bail. otherwise check the keychain.
|
||||
NSString* realm = [NSString stringWithCString:host.get()];
|
||||
if ( [keychain isHostInDenyList:realm] )
|
||||
return NS_OK;
|
||||
|
||||
//
|
||||
// If there's already an entry in the keychain, check if the username
|
||||
// and password match. If not, ask the user what they want to do and replace
|
||||
// it as necessary. If there's no entry, ask if they want to remember it
|
||||
// and then put it into the keychain
|
||||
//
|
||||
NSString* realm = [NSString stringWithCString:host.get()];
|
||||
NSString* existingUser = [NSMutableString string];
|
||||
NSString* existingPassword = [NSMutableString string];
|
||||
KCItemRef itemRef;
|
||||
BOOL foundExistingPassword = [mKeychain getUsernameAndPassword:realm port:port user:existingUser password:existingPassword item:&itemRef];
|
||||
BOOL foundExistingPassword = [keychain getUsernameAndPassword:realm port:port user:existingUser password:existingPassword item:&itemRef];
|
||||
if ( foundExistingPassword ) {
|
||||
if ( !([existingUser isEqualToString:username] && [existingPassword isEqualToString:password]) )
|
||||
if ( CheckChangeDataYN(window) )
|
||||
[mKeychain updateUsernameAndPassword:realm port:port user:username password:password item:itemRef];
|
||||
[keychain updateUsernameAndPassword:realm port:port user:username password:password item:itemRef];
|
||||
}
|
||||
else {
|
||||
if (CheckStorePasswordYN(window))
|
||||
[mKeychain storeUsernameAndPassword:realm port:port user:username password:password];
|
||||
switch (CheckStorePasswordYN(window)) {
|
||||
case kSave:
|
||||
[keychain storeUsernameAndPassword:realm port:port user:username password:password];
|
||||
break;
|
||||
|
||||
case kNeverRemember:
|
||||
// tell the keychain we never want to be prompted about this host again
|
||||
[keychain addHostToDenyList:realm];
|
||||
break;
|
||||
|
||||
case kDontRemember:
|
||||
// do nothing at all
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,12 +841,11 @@ KeychainFormSubmitObserver::GetNSWindow(nsIDOMWindowInternal* inWindow)
|
|||
return nswindow;
|
||||
}
|
||||
|
||||
BOOL
|
||||
KeychainPromptResult
|
||||
KeychainFormSubmitObserver::CheckStorePasswordYN(nsIDOMWindowInternal* window)
|
||||
{
|
||||
NSWindow* nswindow = GetNSWindow(window);
|
||||
nsAlertController* dialog = CHBrowserService::GetAlertController();
|
||||
return [dialog confirmStorePassword:nswindow];
|
||||
return [[KeychainService instance] confirmStorePassword:nswindow];
|
||||
}
|
||||
|
||||
|
||||
|
@ -657,16 +853,14 @@ BOOL
|
|||
KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window)
|
||||
{
|
||||
NSWindow* nswindow = GetNSWindow(window);
|
||||
nsAlertController* dialog = CHBrowserService::GetAlertController();
|
||||
return [dialog confirmChangedPassword:nswindow];
|
||||
return [[KeychainService instance] confirmChangedPassword:nswindow];
|
||||
}
|
||||
|
||||
@implementation KeychainBrowserListener
|
||||
|
||||
- (id)initWithBrowser:(KeychainService*)keychain browser:(CHBrowserView*)aBrowser
|
||||
- (id)initWithBrowser:(CHBrowserView*)aBrowser
|
||||
{
|
||||
if ( (self = [super init]) ) {
|
||||
mKeychain = keychain;
|
||||
mBrowserView = aBrowser;
|
||||
}
|
||||
return self;
|
||||
|
@ -683,7 +877,8 @@ KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window)
|
|||
if(!succeeded)
|
||||
return;
|
||||
|
||||
if(![mKeychain isEnabled] || ![mKeychain isAutoFillEnabled])
|
||||
KeychainService* keychain = [KeychainService instance];
|
||||
if(![keychain isEnabled] || ![keychain isAutoFillEnabled])
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> domWin = getter_AddRefs([mBrowserView getContentWindow]);
|
||||
|
@ -750,7 +945,7 @@ KeychainFormSubmitObserver::CheckChangeDataYN(nsIDOMWindowInternal* window)
|
|||
docURL->GetPort(&port);
|
||||
|
||||
KCItemRef ignore;
|
||||
if ([mKeychain getUsernameAndPassword:hostStr port:port user:username password:password item:&ignore]) {
|
||||
if ([keychain getUsernameAndPassword:hostStr port:port user:username password:password item:&ignore]) {
|
||||
nsAutoString user, pwd;
|
||||
[username assignTo_nsAString:user];
|
||||
[password assignTo_nsAString:pwd];
|
||||
|
|
|
@ -286,7 +286,7 @@ static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& o
|
|||
NSImage* faviconImage = nil;
|
||||
|
||||
NS_DURING
|
||||
faviconImage = [[NSImage alloc] initWithData:data];
|
||||
faviconImage = [[[NSImage alloc] initWithData:data] autorelease];
|
||||
NS_HANDLER
|
||||
NSLog(@"Exception \"%@ making\" favicon image for %@", localException, inURI);
|
||||
faviconImage = nil;
|
||||
|
|
|
@ -53,8 +53,6 @@
|
|||
IBOutlet id confirmPanelText;
|
||||
IBOutlet id confirmPanelButton1;
|
||||
IBOutlet id confirmPanelButton2;
|
||||
IBOutlet id confirmStorePasswordPanel;
|
||||
IBOutlet id confirmChangePasswordPanel;
|
||||
IBOutlet id promptPanel;
|
||||
IBOutlet id promptPanelCheck;
|
||||
IBOutlet id promptPanelText;
|
||||
|
@ -90,8 +88,6 @@
|
|||
- (int)confirmCheckEx:(NSWindow*)parent title:(NSString*)title text:(NSString*)text
|
||||
button1:(NSString*)btn1 button2:(NSString*)btn2 button3:(NSString*)btn3
|
||||
checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue;
|
||||
- (BOOL)confirmStorePassword:(NSWindow*)parent;
|
||||
- (BOOL)confirmChangedPassword:(NSWindow*)parent;
|
||||
|
||||
- (BOOL)prompt:(NSWindow*)parent title:(NSString*)title text:(NSString*)text promptText:(NSMutableString*)promptText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck;
|
||||
- (BOOL)promptUserNameAndPassword:(NSWindow*)parent title:(NSString*)title text:(NSString*)text userNameText:(NSMutableString*)userNameText passwordText:(NSMutableString*)passwordText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck;
|
||||
|
|
|
@ -154,19 +154,6 @@ enum { kOKButton = 0, kCancelButton = 1, kOtherButton = 2 };
|
|||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)confirmStorePassword:(NSWindow*)parent
|
||||
{
|
||||
int result = [NSApp runModalForWindow:confirmStorePasswordPanel relativeToWindow:parent];
|
||||
[confirmStorePasswordPanel close];
|
||||
return (result == kOKButton);
|
||||
}
|
||||
|
||||
- (BOOL)confirmChangedPassword:(NSWindow*)parent
|
||||
{
|
||||
int result = [NSApp runModalForWindow:confirmChangePasswordPanel relativeToWindow:parent];
|
||||
[confirmChangePasswordPanel close];
|
||||
return (result == kOKButton);
|
||||
}
|
||||
|
||||
- (BOOL)prompt:(NSWindow*)parent title:(NSString*)title text:(NSString*)text promptText:(NSMutableString*)promptText checkMsg:(NSString*)checkMsg checkValue:(BOOL*)checkValue doCheck:(BOOL)doCheck
|
||||
{
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -38,49 +40,72 @@
|
|||
#import <AppKit/AppKit.h>
|
||||
|
||||
#import "CHDownloadProgressDisplay.h"
|
||||
#import "CHStackView.h"
|
||||
|
||||
#include "nscore.h"
|
||||
/*
|
||||
How ProgressViewController and ProgressDlgController work.
|
||||
|
||||
ProgressDlgController manages the window the the downloads are displayed in.
|
||||
It contains a single CHStackView, a custom class that asks its datasource
|
||||
for a list of views to display, in a similar fashion to the way NSTableView
|
||||
asks its datasource for data to display. There is a single instance of
|
||||
ProgressDlgController, returned by +sharedDownloadController.
|
||||
|
||||
The ProgressDlgController is a subclass of CHDownloadController, which
|
||||
means that it gets asked to create new objects conforming to the
|
||||
CHDownloadProgressDisplay protocol, which are used to display
|
||||
the progress of a single download. It does so by returning instances of
|
||||
ProgressViewController, which manage an NSView that contains a progress
|
||||
indicator, some text fields for status info and a cancel button.
|
||||
|
||||
After a ProgressViewController is requested, the CHStackView is reloaded,
|
||||
which causes it to ask the ProgressDlgController (it's datasource) to
|
||||
provide it with a list of all the subviews to be diaplyed. It calculates
|
||||
it's new frame, and arranges the subviews in a vertical list.
|
||||
|
||||
The ProgressDlgController now needs to resize its window. It knows when
|
||||
to do this because is watches for changes in the CHStackViews frame (using
|
||||
NSViews built in NSNotification for this).
|
||||
|
||||
|
||||
Expanding/contracting download progress views
|
||||
|
||||
When a disclosure triangle is clicked, the ProgressViewController just swaps
|
||||
the expanded view for a smaller one. It saves the new state as the users
|
||||
preference for "browser.download.compactView". If the option key was held down,
|
||||
a notification is posted (that all ProgressViewControllers listen for) that
|
||||
makes all ProgressViewControllers change their state to the new state of the sender.
|
||||
|
||||
class nsIWebBrowserPersist;
|
||||
class nsISupports;
|
||||
class nsIInputStream;
|
||||
class nsDownloadListener;
|
||||
*/
|
||||
|
||||
#import "CHDownloadProgressDisplay.h"
|
||||
|
||||
@interface ChimeraDownloadControllerFactory : DownloadControllerFactory
|
||||
@end
|
||||
|
||||
|
||||
@interface ProgressDlgController : NSWindowController <CHDownloadProgressDisplay>
|
||||
@interface ProgressDlgController : NSWindowController<CHDownloadDisplayFactory, CHStackViewDataSource>
|
||||
{
|
||||
IBOutlet NSTextField *mElapsedTimeLabel;
|
||||
IBOutlet NSTextField *mFromField;
|
||||
IBOutlet NSTextField *mStatusLabel;
|
||||
IBOutlet NSTextField *mTimeLeftLabel;
|
||||
IBOutlet NSTextField *mToField;
|
||||
IBOutlet NSProgressIndicator *mProgressBar;
|
||||
|
||||
NSToolbarItem *leaveOpenToggleToolbarItem;
|
||||
|
||||
BOOL mSaveFileDialogShouldStayOpen;
|
||||
BOOL mDoingAutoFileDownload;
|
||||
BOOL mIsFileSave;
|
||||
BOOL mDownloadIsComplete;
|
||||
long mCurrentProgress; // if progress bar is indeterminate, can still calc stats.
|
||||
|
||||
CHDownloader *mDownloader; // we hold a ref to this
|
||||
NSTimer *mDownloadTimer;
|
||||
IBOutlet CHStackView *mStackView;
|
||||
IBOutlet NSScrollView *mScrollView;
|
||||
IBOutlet NSTextField *mNoDownloadsText;
|
||||
|
||||
NSSize mDefaultWindowSize;
|
||||
NSTimer *mDownloadTimer;
|
||||
NSMutableArray *mProgressViewControllers;
|
||||
int mNumActiveDownloads;
|
||||
}
|
||||
|
||||
+ (int)numDownloadInProgress;
|
||||
+ (ProgressDlgController *)sharedDownloadController;
|
||||
|
||||
-(void)autosaveWindowFrame;
|
||||
- (int)numDownloadsInProgress;
|
||||
|
||||
-(void) setupDownloadTimer;
|
||||
-(void) killDownloadTimer;
|
||||
-(void) setDownloadProgress:(NSTimer *)aTimer;
|
||||
-(NSString *) formatTime:(int)aSeconds;
|
||||
-(NSString *) formatFuzzyTime:(int)aSeconds;
|
||||
-(NSString *) formatBytes:(float)aBytes;
|
||||
- (void)autosaveWindowFrame;
|
||||
|
||||
- (void)setupDownloadTimer;
|
||||
- (void)killDownloadTimer;
|
||||
- (void)setDownloadProgress:(NSTimer *)aTimer;
|
||||
|
||||
- (void)didStartDownload:(id <CHDownloadProgressDisplay>)progressDisplay;
|
||||
- (void)didEndDownload:(id <CHDownloadProgressDisplay>)progressDisplay;
|
||||
- (void)removeDownload:(id <CHDownloadProgressDisplay>)progressDisplay;
|
||||
|
||||
- (NSApplicationTerminateReply)allowTerminate;
|
||||
|
||||
@end
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -35,504 +36,319 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "NSView+Utils.h"
|
||||
|
||||
#import "ProgressDlgController.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nsIWebBrowserPersist.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIDownload.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIPref.h"
|
||||
|
||||
static NSString *SaveFileToolbarIdentifier = @"Save File Dialog Toolbar";
|
||||
static NSString *CancelToolbarItemIdentifier = @"Cancel Toolbar Item";
|
||||
static NSString *ShowFileToolbarItemIdentifier = @"Show File Toolbar Item";
|
||||
static NSString *OpenFileToolbarItemIdentifier = @"Open File Toolbar Item";
|
||||
static NSString *LeaveOpenToolbarItemIdentifier = @"Leave Open Toggle Toolbar Item";
|
||||
#import "ProgressViewController.h"
|
||||
#import "PreferenceManager.h"
|
||||
|
||||
static NSString *ProgressWindowFrameSaveName = @"ProgressWindow";
|
||||
|
||||
@implementation ChimeraDownloadControllerFactory : DownloadControllerFactory
|
||||
|
||||
- (NSWindowController<CHDownloadProgressDisplay> *)createDownloadController
|
||||
{
|
||||
NSWindowController* progressController = [[ProgressDlgController alloc] initWithWindowNibName: @"ProgressDialog"];
|
||||
NSAssert([progressController conformsToProtocol:@protocol(CHDownloadProgressDisplay)],
|
||||
@"progressController should conform to CHDownloadProgressDisplay protocol");
|
||||
return progressController;
|
||||
}
|
||||
|
||||
@interface ProgressDlgController(PrivateProgressDlgController)
|
||||
|
||||
- (void)resizeWindowToFit;
|
||||
- (void)rebuildViews;
|
||||
- (NSSize)windowSizeForStackSize:(NSSize)stackSize;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
@interface ProgressDlgController(Private)
|
||||
-(void)setupToolbar;
|
||||
@end
|
||||
|
||||
@implementation ProgressDlgController
|
||||
|
||||
static int gNumActiveDownloads = 0;
|
||||
static id gSharedProgressController = nil;
|
||||
|
||||
+ (int)numDownloadInProgress
|
||||
+ (ProgressDlgController *)sharedDownloadController;
|
||||
{
|
||||
return gNumActiveDownloads;
|
||||
if (gSharedProgressController == nil)
|
||||
gSharedProgressController = [[ProgressDlgController alloc] init];
|
||||
|
||||
return gSharedProgressController;
|
||||
}
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self == [super initWithWindowNibName:@"ProgressDialog"]))
|
||||
{
|
||||
// Register for notifications when the stack view changes size
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(stackViewResized:)
|
||||
name:StackViewResizedNotificationName
|
||||
object:nil];
|
||||
|
||||
mProgressViewControllers = [[NSMutableArray alloc] init];
|
||||
|
||||
mDefaultWindowSize = [[self window] frame].size;
|
||||
// it would be nice if we could get the frame from the name, and then
|
||||
// mess with it before setting it.
|
||||
[[self window] setFrameUsingName:ProgressWindowFrameSaveName];
|
||||
// set the window to its default height
|
||||
NSRect windowFrame = [[self window] frame];
|
||||
windowFrame.size.height = mDefaultWindowSize.height;
|
||||
[[self window] setFrame:windowFrame display:NO];
|
||||
|
||||
// We provide the views for the stack view, from mProgressViewControllers
|
||||
[mStackView setDataSource:self];
|
||||
|
||||
[mScrollView setDrawsBackground:NO];
|
||||
[mNoDownloadsText retain]; // so we can remove it from its superview
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// if we get here because we're quitting, the listener will still be alive
|
||||
// yet we're going away. As a result, we need to tell the d/l listener to
|
||||
// forget it ever met us and necko will clean it up on its own.
|
||||
if ( mDownloader)
|
||||
mDownloader->DetachDownloadDisplay();
|
||||
NS_IF_RELEASE(mDownloader);
|
||||
if (self == gSharedProgressController)
|
||||
gSharedProgressController = nil;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[mProgressViewControllers release];
|
||||
[mNoDownloadsText release];
|
||||
[self killDownloadTimer];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)windowDidLoad
|
||||
- (void)didStartDownload:(id <CHDownloadProgressDisplay>)progressDisplay
|
||||
{
|
||||
[super windowDidLoad];
|
||||
|
||||
mDownloadIsComplete = NO;
|
||||
mDoingAutoFileDownload = NO;
|
||||
[self showWindow:nil]; // make sure the window is visible
|
||||
|
||||
if (!mIsFileSave) {
|
||||
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
|
||||
PRBool save = PR_FALSE;
|
||||
prefs->GetBoolPref("browser.download.progressDnldDialog.keepAlive", &save);
|
||||
mSaveFileDialogShouldStayOpen = save;
|
||||
|
||||
PRBool autoHelperDispatch = PR_FALSE;
|
||||
prefs->GetBoolPref("browser.download.autoDispatch", &autoHelperDispatch);
|
||||
mDoingAutoFileDownload = autoHelperDispatch;
|
||||
[self rebuildViews];
|
||||
[self setupDownloadTimer];
|
||||
}
|
||||
|
||||
- (void)didEndDownload:(id <CHDownloadProgressDisplay>)progressDisplay
|
||||
{
|
||||
[self rebuildViews]; // to swap in the completed view
|
||||
}
|
||||
|
||||
- (void)removeDownload:(id <CHDownloadProgressDisplay>)progressDisplay
|
||||
{
|
||||
[mProgressViewControllers removeObject:progressDisplay];
|
||||
|
||||
if ([mProgressViewControllers count] == 0)
|
||||
{
|
||||
// Stop doing stuff if there aren't any downloads going on
|
||||
[self killDownloadTimer];
|
||||
}
|
||||
|
||||
[self setupToolbar];
|
||||
[mProgressBar setUsesThreadedAnimation:YES];
|
||||
[mProgressBar startAnimation:self]; // move to onStateChange
|
||||
[self rebuildViews];
|
||||
}
|
||||
|
||||
- (void)setupToolbar
|
||||
- (void)stackViewResized:(NSNotification *)notification
|
||||
{
|
||||
NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:SaveFileToolbarIdentifier] autorelease];
|
||||
|
||||
[toolbar setDisplayMode:NSToolbarDisplayModeDefault];
|
||||
[toolbar setAllowsUserCustomization:YES];
|
||||
[toolbar setAutosavesConfiguration:YES];
|
||||
[toolbar setDelegate:self];
|
||||
[[self window] setToolbar:toolbar];
|
||||
NSDictionary* userInfo = [notification userInfo];
|
||||
NSSize oldStackSize = [[userInfo objectForKey:@"oldsize"] sizeValue];
|
||||
|
||||
// this code is used to auto-resize the downloads window when
|
||||
// its contents change size, if the window is in its standard, "zoomed"
|
||||
// state. This allows the user to choose between auto-resizing behavior,
|
||||
// by leaving the window alone, or their own size, by resizing it.
|
||||
|
||||
// get the size the window would have been if it had been in the
|
||||
// standard state, given the old size of the contents
|
||||
NSSize oldZoomedWindowSize = [self windowSizeForStackSize:oldStackSize];
|
||||
NSSize curWindowSize = [[self window] frame].size;
|
||||
|
||||
// only resize if the window matches the stack size
|
||||
if (CHCloseSizes(oldZoomedWindowSize, curWindowSize, 4.0))
|
||||
[self resizeWindowToFit];
|
||||
}
|
||||
|
||||
- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
|
||||
// given the dimensions of our stack view, return the dimensions of the window,
|
||||
// assuming the window is zoomed to show as much of the contents as possible.
|
||||
- (NSSize)windowSizeForStackSize:(NSSize)stackSize
|
||||
{
|
||||
return [NSArray arrayWithObjects: CancelToolbarItemIdentifier,
|
||||
ShowFileToolbarItemIdentifier,
|
||||
OpenFileToolbarItemIdentifier,
|
||||
LeaveOpenToolbarItemIdentifier,
|
||||
NSToolbarCustomizeToolbarItemIdentifier,
|
||||
NSToolbarFlexibleSpaceItemIdentifier,
|
||||
NSToolbarSpaceItemIdentifier,
|
||||
NSToolbarSeparatorItemIdentifier,
|
||||
nil];
|
||||
NSSize actualScrollFrame = [mScrollView frame].size;
|
||||
NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:stackSize
|
||||
hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder];
|
||||
|
||||
// frameSizeForContentSize seems to return a width 1 pixel too narrow
|
||||
scrollFrameSize.width += 1;
|
||||
|
||||
NSRect contentRect = [[[self window] contentView] frame];
|
||||
contentRect.size.width += scrollFrameSize.width - actualScrollFrame.width;
|
||||
contentRect.size.height += scrollFrameSize.height - actualScrollFrame.height;
|
||||
contentRect.origin = [[self window] convertBaseToScreen:contentRect.origin]; // convert to screen
|
||||
|
||||
NSRect advisoryWindowFrame = [NSWindow frameRectForContentRect:contentRect styleMask:[[self window] styleMask]];
|
||||
NSRect constrainedRect = [[self window] constrainFrameRect:advisoryWindowFrame toScreen:[[self window] screen]];
|
||||
return constrainedRect.size;
|
||||
}
|
||||
|
||||
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
|
||||
- (void)resizeWindowToFit
|
||||
{
|
||||
return [NSArray arrayWithObjects: CancelToolbarItemIdentifier,
|
||||
NSToolbarFlexibleSpaceItemIdentifier,
|
||||
LeaveOpenToolbarItemIdentifier,
|
||||
NSToolbarFlexibleSpaceItemIdentifier,
|
||||
ShowFileToolbarItemIdentifier,
|
||||
OpenFileToolbarItemIdentifier,
|
||||
nil];
|
||||
if ([mProgressViewControllers count] > 0)
|
||||
{
|
||||
NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:[mStackView bounds].size
|
||||
hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder];
|
||||
NSSize curScrollFrameSize = [mScrollView frame].size;
|
||||
|
||||
NSRect windowFrame = [[self window] frame];
|
||||
|
||||
float frameDelta = (scrollFrameSize.height - curScrollFrameSize.height);
|
||||
windowFrame.size.height += frameDelta;
|
||||
windowFrame.origin.y -= frameDelta; // maintain top
|
||||
|
||||
[[self window] setFrame:windowFrame display:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
|
||||
- (void)rebuildViews
|
||||
{
|
||||
if ([toolbarItem action] == @selector(cancel)) // cancel button
|
||||
return (!mDownloadIsComplete);
|
||||
if ([toolbarItem action] == @selector(pauseAndResumeDownload)) // pause/resume button
|
||||
return (NO); // Hey - it hasn't been hooked up yet. !mDownloadIsComplete when it is.
|
||||
if ([toolbarItem action] == @selector(showFile)) // show file
|
||||
return (mDownloadIsComplete);
|
||||
if ([toolbarItem action] == @selector(openFile)) // open file
|
||||
return (mDownloadIsComplete);
|
||||
return YES; // turn it on otherwise.
|
||||
[mStackView reloadSubviews];
|
||||
|
||||
if ([mProgressViewControllers count] == 0)
|
||||
{
|
||||
[[[self window] contentView] addSubview:mNoDownloadsText];
|
||||
}
|
||||
else
|
||||
{
|
||||
[mNoDownloadsText removeFromSuperview];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
- (int)numDownloadsInProgress
|
||||
{
|
||||
unsigned int numViews = [mProgressViewControllers count];
|
||||
int numActive = 0;
|
||||
|
||||
for (unsigned int i = 0; i < numViews; i++)
|
||||
{
|
||||
if ([[mProgressViewControllers objectAtIndex:i] isActive])
|
||||
++numActive;
|
||||
}
|
||||
return numActive;
|
||||
}
|
||||
|
||||
-(void)autosaveWindowFrame
|
||||
{
|
||||
[[self window] saveFrameUsingName: ProgressWindowFrameSaveName];
|
||||
}
|
||||
|
||||
- (NSToolbarItem *) toolbar:(NSToolbar *)toolbar
|
||||
itemForItemIdentifier:(NSString *)itemIdent
|
||||
willBeInsertedIntoToolbar:(BOOL)willBeInserted
|
||||
{
|
||||
NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease];
|
||||
|
||||
if ( [itemIdent isEqual:CancelToolbarItemIdentifier] )
|
||||
{
|
||||
[toolbarItem setLabel:NSLocalizedString(@"Cancel",@"Cancel")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedString(@"CancelPaletteLabel",@"Cancel Download")];
|
||||
[toolbarItem setToolTip:NSLocalizedString(@"CancelToolTip",@"Cancel this file download")];
|
||||
[toolbarItem setImage:[NSImage imageNamed:@"saveCancel"]];
|
||||
[toolbarItem setTarget:self];
|
||||
[toolbarItem setAction:@selector(cancel)];
|
||||
}
|
||||
else if ( [itemIdent isEqual:ShowFileToolbarItemIdentifier] )
|
||||
{
|
||||
[toolbarItem setLabel:NSLocalizedString(@"Show File",@"Show File")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedString(@"Show File",@"Show File")];
|
||||
[toolbarItem setToolTip:NSLocalizedString(@"ShowToolTip",@"Show the saved file in the Finder")];
|
||||
[toolbarItem setImage:[NSImage imageNamed:@"saveShowFile"]];
|
||||
[toolbarItem setTarget:self];
|
||||
[toolbarItem setAction:@selector(showFile)];
|
||||
}
|
||||
else if ( [itemIdent isEqual:OpenFileToolbarItemIdentifier] )
|
||||
{
|
||||
[toolbarItem setLabel:NSLocalizedString(@"Open File",@"Open File")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedString(@"Open File",@"Open File")];
|
||||
[toolbarItem setToolTip:NSLocalizedString(@"OpenToolTip",@"Open the saved file in its default application.")];
|
||||
[toolbarItem setImage:[NSImage imageNamed:@"saveOpenFile"]];
|
||||
[toolbarItem setTarget:self];
|
||||
[toolbarItem setAction:@selector(openFile)];
|
||||
}
|
||||
else if ( [itemIdent isEqual:LeaveOpenToolbarItemIdentifier] )
|
||||
{
|
||||
if ( !mIsFileSave && !mDoingAutoFileDownload )
|
||||
{
|
||||
if ( mSaveFileDialogShouldStayOpen )
|
||||
{
|
||||
[toolbarItem setLabel:NSLocalizedString(@"Leave Open",@"Leave Open")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")];
|
||||
[toolbarItem setToolTip:NSLocalizedString(@"LeaveOpenToolTip",@"Window will stay open when download finishes.")];
|
||||
[toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]];
|
||||
[toolbarItem setTarget:self];
|
||||
[toolbarItem setAction:@selector(toggleLeaveOpen)];
|
||||
}
|
||||
else
|
||||
{
|
||||
[toolbarItem setLabel:NSLocalizedString(@"Close When Done",@"Close When Done")];
|
||||
[toolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")];
|
||||
[toolbarItem setToolTip:NSLocalizedString(@"CloseWhenDoneToolTip",@"Window will close automatically when download finishes.")];
|
||||
[toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]];
|
||||
[toolbarItem setTarget:self];
|
||||
[toolbarItem setAction:@selector(toggleLeaveOpen)];
|
||||
}
|
||||
if ( willBeInserted )
|
||||
{
|
||||
leaveOpenToggleToolbarItem = toolbarItem; //establish reference
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
toolbarItem = nil;
|
||||
}
|
||||
|
||||
return toolbarItem;
|
||||
}
|
||||
|
||||
-(void)cancel
|
||||
{
|
||||
if (mDownloader) // we should always have one
|
||||
mDownloader->CancelDownload();
|
||||
|
||||
// clean up downloaded file. - do it here on in CancelDownload?
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSString *thePath = [[mToField stringValue] stringByExpandingTildeInPath];
|
||||
if ([fileManager isDeletableFileAtPath:thePath])
|
||||
// if we delete it, fantastic. if not, oh well. better to move to trash instead?
|
||||
[fileManager removeFileAtPath:thePath handler:nil];
|
||||
|
||||
// we can _not_ set the |mDownloadIsComplete| flag here because the download really
|
||||
// isn't done yet. We'll probably continue to process more PLEvents that are already
|
||||
// in the queue until we get a STATE_STOP state change. As a result, we just keep
|
||||
// going until that comes in (and it will, because we called CancelDownload() above).
|
||||
// Ensure that the window goes away when we get there by flipping the 'stay alive'
|
||||
// flag. (bug 154913)
|
||||
mSaveFileDialogShouldStayOpen = NO;
|
||||
}
|
||||
|
||||
-(void)showFile
|
||||
{
|
||||
NSString *theFile = [[mToField stringValue] stringByExpandingTildeInPath];
|
||||
if ([[NSWorkspace sharedWorkspace] selectFile:theFile
|
||||
inFileViewerRootedAtPath:[theFile stringByDeletingLastPathComponent]])
|
||||
return;
|
||||
// hmmm. it didn't work. that's odd. need localized error messages. for now, just beep.
|
||||
NSBeep();
|
||||
}
|
||||
|
||||
-(void)openFile
|
||||
{
|
||||
NSString *theFile = [[mToField stringValue] stringByExpandingTildeInPath];
|
||||
if ([[NSWorkspace sharedWorkspace] openFile:theFile])
|
||||
return;
|
||||
// hmmm. it didn't work. that's odd. need localized error message. for now, just beep.
|
||||
NSBeep();
|
||||
|
||||
}
|
||||
|
||||
-(void)toggleLeaveOpen
|
||||
{
|
||||
if ( ! mSaveFileDialogShouldStayOpen ) {
|
||||
mSaveFileDialogShouldStayOpen = YES;
|
||||
[leaveOpenToggleToolbarItem setLabel:NSLocalizedString(@"Leave Open",@"Leave Open")];
|
||||
[leaveOpenToggleToolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")];
|
||||
[leaveOpenToggleToolbarItem setToolTip:NSLocalizedString(@"LeaveOpenToolTip",@"Window will stay open when download finishes.")];
|
||||
[leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]];
|
||||
} else {
|
||||
mSaveFileDialogShouldStayOpen = NO;
|
||||
[leaveOpenToggleToolbarItem setLabel:NSLocalizedString(@"Close When Done",@"Close When Done")];
|
||||
[leaveOpenToggleToolbarItem setPaletteLabel:NSLocalizedString(@"Toggle Close Behavior",@"Toggle Close Behavior")];
|
||||
[leaveOpenToggleToolbarItem setToolTip:NSLocalizedString(@"CloseWhenDoneToolTip",@"Window will close automatically when download finishes.")];
|
||||
[leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]];
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
|
||||
prefs->SetBoolPref("browser.download.progressDnldDialog.keepAlive", mSaveFileDialogShouldStayOpen);
|
||||
[[self window] saveFrameUsingName:ProgressWindowFrameSaveName];
|
||||
}
|
||||
|
||||
- (void)windowWillClose:(NSNotification *)notification
|
||||
{
|
||||
[self autosaveWindowFrame];
|
||||
[self autorelease];
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(NSNotification *)notification
|
||||
{
|
||||
[self killDownloadTimer];
|
||||
if (!mDownloadIsComplete) { //whoops. hard cancel.
|
||||
[self cancel];
|
||||
return NO; // let setDownloadProgress handle the close.
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)killDownloadTimer
|
||||
{
|
||||
if (mDownloadTimer) {
|
||||
if (mDownloadTimer)
|
||||
{
|
||||
[mDownloadTimer invalidate];
|
||||
[mDownloadTimer release];
|
||||
mDownloadTimer = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupDownloadTimer
|
||||
{
|
||||
[self killDownloadTimer];
|
||||
mDownloadTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0
|
||||
target:self
|
||||
selector:@selector(setDownloadProgress:)
|
||||
userInfo:nil
|
||||
repeats:YES] retain];
|
||||
}
|
||||
|
||||
-(NSString *)formatTime:(int)seconds
|
||||
{
|
||||
NSMutableString *theTime =[[[NSMutableString alloc] initWithCapacity:8] autorelease];
|
||||
[theTime setString:@""];
|
||||
NSString *padZero = [NSString stringWithString:@"0"];
|
||||
//write out new elapsed time
|
||||
if (seconds >= 3600){
|
||||
[theTime appendFormat:@"%d:",(seconds / 3600)];
|
||||
seconds = seconds % 3600;
|
||||
}
|
||||
NSString *elapsedMin = [NSString stringWithFormat:@"%d:",(seconds / 60)];
|
||||
if ([elapsedMin length] == 2)
|
||||
[theTime appendString:[padZero stringByAppendingString:elapsedMin]];
|
||||
else
|
||||
[theTime appendString:elapsedMin];
|
||||
seconds = seconds % 60;
|
||||
NSString *elapsedSec = [NSString stringWithFormat:@"%d",seconds];
|
||||
if ([elapsedSec length] == 2)
|
||||
[theTime appendString:elapsedSec];
|
||||
else
|
||||
[theTime appendString:[padZero stringByAppendingString:elapsedSec]];
|
||||
return theTime;
|
||||
}
|
||||
// fuzzy time gives back strings like "about 5 seconds"
|
||||
-(NSString *)formatFuzzyTime:(int)seconds
|
||||
{
|
||||
// check for seconds first
|
||||
if (seconds < 60) {
|
||||
if (seconds < 7)
|
||||
return [[[NSString alloc] initWithFormat:NSLocalizedString(@"UnderSec",@"Under %d seconds"),5] autorelease];
|
||||
if (seconds < 13)
|
||||
return [[[NSString alloc] initWithFormat:NSLocalizedString(@"UnderSec",@"Under %d seconds"),10] autorelease];
|
||||
return [[[NSString alloc] initWithString:NSLocalizedString(@"UnderMin",@"Under a minute")] autorelease];
|
||||
}
|
||||
// seconds becomes minutes and we keep checking.
|
||||
seconds = seconds/60;
|
||||
if (seconds < 60) {
|
||||
if (seconds < 2)
|
||||
return [[[NSString alloc] initWithString:NSLocalizedString(@"AboutMin",@"About a minute")] autorelease];
|
||||
// OK, tell the good people how much time we have left.
|
||||
return [[[NSString alloc] initWithFormat:NSLocalizedString(@"AboutMins",@"About %d minutes"),seconds] autorelease];
|
||||
}
|
||||
//this download will never seemingly never end. now seconds become hours.
|
||||
seconds = seconds/60;
|
||||
if (seconds < 2)
|
||||
return [[[NSString alloc] initWithString:NSLocalizedString(@"AboutHour",@"Over an hour")] autorelease];
|
||||
return [[[NSString alloc] initWithFormat:NSLocalizedString(@"AboutHours",@"Over %d hours"),seconds] autorelease];
|
||||
}
|
||||
|
||||
|
||||
-(NSString *)formatBytes:(float)bytes
|
||||
{ // this is simpler than my first try. I peaked at Omnigroup byte formatting code.
|
||||
// if bytes are negative, we return question marks.
|
||||
if (bytes < 0)
|
||||
return [[[NSString alloc] initWithString:@"???"] autorelease];
|
||||
// bytes first.
|
||||
if (bytes < 1024)
|
||||
return [[[NSString alloc] initWithFormat:@"%.1f bytes",bytes] autorelease];
|
||||
// kb
|
||||
bytes = bytes/1024;
|
||||
if (bytes < 1024)
|
||||
return [[[NSString alloc] initWithFormat:@"%.1f KB",bytes] autorelease];
|
||||
// mb
|
||||
bytes = bytes/1024;
|
||||
if (bytes < 1024)
|
||||
return [[[NSString alloc] initWithFormat:@"%.1f MB",bytes] autorelease];
|
||||
// gb
|
||||
bytes = bytes/1024;
|
||||
return [[[NSString alloc] initWithFormat:@"%.1f GB",bytes] autorelease];
|
||||
}
|
||||
|
||||
// this handles lots of things.
|
||||
- (void)setDownloadProgress:(NSTimer *)downloadTimer;
|
||||
{
|
||||
// XXX this logic needs cleaning up.
|
||||
|
||||
// Ack! we're closing the window with the download still running!
|
||||
if (mDownloadIsComplete)
|
||||
mDownloadTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0
|
||||
target:self
|
||||
selector:@selector(setDownloadProgress:)
|
||||
userInfo:nil
|
||||
repeats:YES] retain];
|
||||
}
|
||||
|
||||
// Called by our timer to refresh all the download stats
|
||||
- (void)setDownloadProgress:(NSTimer *)aTimer
|
||||
{
|
||||
[mProgressViewControllers makeObjectsPerformSelector:@selector(refreshDownloadInfo)];
|
||||
// if the window is minimized, we want to update the dock image here. But how?
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)allowTerminate
|
||||
{
|
||||
if ([self numDownloadsInProgress] > 0)
|
||||
{
|
||||
[[self window] performClose:self];
|
||||
return;
|
||||
// make sure the window is visible
|
||||
[self showWindow:self];
|
||||
|
||||
NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?");
|
||||
NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @"");
|
||||
NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel");
|
||||
NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit");
|
||||
|
||||
// while the panel is up, download dialogs won't update (no timers firing) but
|
||||
// downloads continue (PLEvents being processed)
|
||||
id panel = NSGetAlertPanel(alert, message, okButton, altButton, nil, message);
|
||||
|
||||
[NSApp beginSheet:panel
|
||||
modalForWindow:[self window]
|
||||
modalDelegate:self
|
||||
didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
|
||||
contextInfo:NULL];
|
||||
int sheetResult = [NSApp runModalForWindow: panel];
|
||||
[NSApp endSheet: panel];
|
||||
[panel orderOut: self];
|
||||
NSReleaseAlertPanel(panel);
|
||||
|
||||
return (sheetResult == NSAlertDefaultReturn) ? NSTerminateCancel : NSTerminateNow;
|
||||
}
|
||||
// get the elapsed time
|
||||
NSArray *elapsedTimeArray = [[mElapsedTimeLabel stringValue] componentsSeparatedByString:@":"];
|
||||
int j = [elapsedTimeArray count];
|
||||
int elapsedSec = [[elapsedTimeArray objectAtIndex:(j-1)] intValue] + [[elapsedTimeArray objectAtIndex:(j-2)] intValue]*60;
|
||||
if (j==3) // this download is taking forever.
|
||||
elapsedSec += [[elapsedTimeArray objectAtIndex:0] intValue]*3600;
|
||||
// update elapsed time
|
||||
[mElapsedTimeLabel setStringValue:[self formatTime:(++elapsedSec)]];
|
||||
// for status field & time left
|
||||
float maxBytes = ([mProgressBar maxValue]);
|
||||
float byteSec = mCurrentProgress/elapsedSec;
|
||||
// OK - if downloadTimer is nil, we're done - fix maxBytes value for status report.
|
||||
if (!downloadTimer)
|
||||
maxBytes = mCurrentProgress;
|
||||
// update status field
|
||||
NSString *labelString = NSLocalizedString(@"LabelString",@"%@ of %@ total (at %@/sec)");
|
||||
[mStatusLabel setStringValue: [NSString stringWithFormat:labelString, [self formatBytes:mCurrentProgress], [self formatBytes:maxBytes], [self formatBytes:byteSec]]];
|
||||
// updating estimated time left field
|
||||
// if maxBytes < 0, can't calc time left.
|
||||
// if !downloadTimer, download is finished. either way, make sure time left is 0.
|
||||
if ((maxBytes > 0) && (downloadTimer))
|
||||
{
|
||||
int secToGo = (int)ceil((elapsedSec*maxBytes/mCurrentProgress) - elapsedSec);
|
||||
[mTimeLeftLabel setStringValue:[self formatFuzzyTime:secToGo]];
|
||||
}
|
||||
else if (!downloadTimer)
|
||||
{ // download done. Set remaining time to 0, fix progress bar & cancel button
|
||||
mDownloadIsComplete = YES; // all done. we got a STATE_STOP
|
||||
[mTimeLeftLabel setStringValue:@""];
|
||||
[self setProgressTo:mCurrentProgress ofMax:mCurrentProgress];
|
||||
if (!mSaveFileDialogShouldStayOpen || mDoingAutoFileDownload)
|
||||
[[self window] performClose:self]; // close window
|
||||
else
|
||||
[[self window] update]; // redraw window
|
||||
}
|
||||
else //maxBytes is undetermined. Set remaining time to question marks.
|
||||
[mTimeLeftLabel setStringValue:@"???"];
|
||||
|
||||
return NSTerminateNow;
|
||||
}
|
||||
|
||||
- (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[NSApp stopModalWithCode:returnCode];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// CHDownloadProgressDisplay protocol methods
|
||||
|
||||
- (void)onStartDownload:(BOOL)isFileSave;
|
||||
// implement to zoom to a size that just fits the contents
|
||||
- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame
|
||||
{
|
||||
mIsFileSave = isFileSave;
|
||||
NSSize scrollFrameSize = [NSScrollView frameSizeForContentSize:[mStackView bounds].size
|
||||
hasHorizontalScroller:NO hasVerticalScroller:YES borderType:NSNoBorder];
|
||||
|
||||
[self window]; // make the window
|
||||
[[self window] setFrameUsingName: ProgressWindowFrameSaveName];
|
||||
NSSize curScrollFrameSize = [mScrollView frame].size;
|
||||
float frameDelta = (scrollFrameSize.height - curScrollFrameSize.height);
|
||||
|
||||
[self showWindow: self];
|
||||
[self setupDownloadTimer];
|
||||
|
||||
gNumActiveDownloads++;
|
||||
NSRect windowFrame = [[self window] frame];
|
||||
windowFrame.size.height += frameDelta;
|
||||
windowFrame.origin.y -= frameDelta; // maintain top
|
||||
|
||||
windowFrame.size.width = mDefaultWindowSize.width;
|
||||
// cocoa will ensure that the window fits onscreen for us
|
||||
return windowFrame;
|
||||
}
|
||||
|
||||
- (void)onEndDownload
|
||||
#pragma mark -
|
||||
|
||||
/*
|
||||
CHStackView datasource methods
|
||||
*/
|
||||
|
||||
- (int)subviewsForStackView:(CHStackView *)stackView
|
||||
{
|
||||
gNumActiveDownloads --;
|
||||
return [mProgressViewControllers count];
|
||||
}
|
||||
|
||||
- (NSView *)viewForStackView:(CHStackView *)aResizingView atIndex:(int)index
|
||||
{
|
||||
return [[mProgressViewControllers objectAtIndex:index] view];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
/*
|
||||
Just create a progress view, but don't display it (otherwise the URL fields etc.
|
||||
are just blank)
|
||||
*/
|
||||
- (id <CHDownloadProgressDisplay>)createProgressDisplay
|
||||
{
|
||||
ProgressViewController *newController = [[ProgressViewController alloc] init];
|
||||
[newController setProgressWindowController:self];
|
||||
[mProgressViewControllers addObject:newController];
|
||||
|
||||
// if we're quitting, our progress window is already gone and we're in the
|
||||
// process of shutting down gecko and all the d/l listeners. The timer, at
|
||||
// that point, is the only thing keeping us alive. Killing it will cause
|
||||
// us to go away immediately, so kung-fu deathgrip it until we're done twiddling
|
||||
// bits on ourself.
|
||||
[self retain]; // Enter The Dragon!
|
||||
[self killDownloadTimer];
|
||||
[self setDownloadProgress:nil];
|
||||
[self release];
|
||||
}
|
||||
|
||||
- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress
|
||||
{
|
||||
mCurrentProgress = aCurProgress; // fall back for stat calcs
|
||||
|
||||
if (![mProgressBar isIndeterminate]) //most likely - just update value
|
||||
{
|
||||
if (aCurProgress == aMaxProgress) //handles little bug in FTP download size
|
||||
[mProgressBar setMaxValue:aMaxProgress];
|
||||
|
||||
[mProgressBar setDoubleValue:aCurProgress];
|
||||
}
|
||||
else if (aMaxProgress > 0) // ok, we're starting up with good max & cur values
|
||||
{
|
||||
[mProgressBar setIndeterminate:NO];
|
||||
[mProgressBar setMaxValue:aMaxProgress];
|
||||
[mProgressBar setDoubleValue:aCurProgress];
|
||||
} // if neither case was true, it's barber pole city.
|
||||
}
|
||||
|
||||
-(void) setDownloadListener: (CHDownloader*)aDownloader
|
||||
{
|
||||
if (mDownloader != aDownloader)
|
||||
NS_IF_RELEASE(mDownloader);
|
||||
|
||||
NS_IF_ADDREF(mDownloader = aDownloader);
|
||||
}
|
||||
|
||||
- (void)setSourceURL:(NSString*)aSourceURL
|
||||
{
|
||||
[mFromField setStringValue: aSourceURL];
|
||||
[mFromField display]; // force an immmeditate update
|
||||
}
|
||||
|
||||
- (void)setDestinationPath:(NSString*)aDestPath
|
||||
{
|
||||
[mToField setStringValue: [aDestPath stringByAbbreviatingWithTildeInPath]];
|
||||
[mToField display]; // force an immmeditate update
|
||||
|
||||
// also set the window title
|
||||
NSString* downloadFileName = [aDestPath lastPathComponent];
|
||||
if ([downloadFileName length] == 0)
|
||||
downloadFileName = aDestPath;
|
||||
|
||||
[[self window] setTitle:[NSString stringWithFormat:NSLocalizedString(@"DownloadingTitle", @""), downloadFileName]];
|
||||
return newController;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "CHDownloadProgressDisplay.h"
|
||||
|
||||
class CHDownloader;
|
||||
@class ProgressDlgController;
|
||||
|
||||
@interface ProgressViewController : NSObject<CHDownloadProgressDisplay>
|
||||
{
|
||||
// we share one progress bar between both views. It's in the expanded
|
||||
// view by default
|
||||
IBOutlet NSProgressIndicator *mProgressBar;
|
||||
|
||||
// in-progress expanded view
|
||||
IBOutlet NSView *mProgressView;
|
||||
IBOutlet NSButton *mExpandedCancelButton;
|
||||
|
||||
// in-progress collapsed view
|
||||
IBOutlet NSView *mProgressViewCompact;
|
||||
|
||||
// completed expanded view
|
||||
IBOutlet NSView *mCompletedView;
|
||||
IBOutlet NSButton *mExpandedRevealButton;
|
||||
IBOutlet NSButton *mExpandedOpenButton;
|
||||
|
||||
// completed collapsed view
|
||||
IBOutlet NSView *mCompletedViewCompact;
|
||||
|
||||
BOOL mViewIsCompact;
|
||||
BOOL mIsFileSave;
|
||||
BOOL mUserCancelled;
|
||||
BOOL mDownloadingError;
|
||||
BOOL mDownloadDone;
|
||||
BOOL mRemoveWhenDone;
|
||||
|
||||
NSTimeInterval mDownloadTime; // only set when done
|
||||
|
||||
long mCurrentProgress; // if progress bar is indeterminate, can still calc stats.
|
||||
long mDownloadSize;
|
||||
|
||||
NSString *mSourceURL;
|
||||
NSString *mDestPath;
|
||||
NSDate *mStartTime;
|
||||
|
||||
CHDownloader *mDownloader; // we hold a ref to this
|
||||
|
||||
ProgressDlgController *mProgressWindowController; // not retained
|
||||
}
|
||||
|
||||
+ (NSString *)formatTime:(int)aSeconds;
|
||||
+ (NSString *)formatFuzzyTime:(int)aSeconds;
|
||||
+ (NSString *)formatBytes:(float)aBytes;
|
||||
|
||||
- (NSView *)view;
|
||||
|
||||
- (IBAction)close:(id)sender;
|
||||
|
||||
- (IBAction)stop:(id)sender;
|
||||
- (IBAction)toggleDisclosure:(id)sender;
|
||||
|
||||
- (IBAction)reveal:(id)sender;
|
||||
- (IBAction)open:(id)sender;
|
||||
|
||||
- (BOOL)isActive;
|
||||
|
||||
- (void)setProgressWindowController:(ProgressDlgController*)progressWindowController;
|
||||
|
||||
@end
|
|
@ -0,0 +1,544 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
|
||||
#import "NSView+Utils.h"
|
||||
|
||||
#import "ProgressViewController.h"
|
||||
#import "ProgressDlgController.h"
|
||||
#import "PreferenceManager.h"
|
||||
|
||||
enum
|
||||
{
|
||||
kLabelTagFilename = 1000,
|
||||
kLabelTagProgress,
|
||||
kLabelTagSource,
|
||||
kLabelTagDestination,
|
||||
kLabelTagTimeRemaining,
|
||||
kLabelTagStatus, // 1005
|
||||
kLabelTagTimeRemainingLabel
|
||||
};
|
||||
|
||||
|
||||
// Notification sent when user holds option key and expands/contracts a progress view
|
||||
static NSString *ProgressViewsShouldResize = @"ProgressViewsShouldResize";
|
||||
|
||||
@interface ProgressViewController(ProgressViewControllerPrivate)
|
||||
|
||||
- (void)viewDidLoad;
|
||||
- (void)refreshDownloadInfo;
|
||||
- (void)moveProgressBarToCurrentView;
|
||||
- (void)updateButtons;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ProgressViewController
|
||||
|
||||
+ (NSString *)formatTime:(int)seconds
|
||||
{
|
||||
NSMutableString *theTime = [NSMutableString stringWithCapacity:8];
|
||||
|
||||
NSString *padZero = [NSString stringWithString:@"0"];
|
||||
//write out new elapsed time
|
||||
if (seconds >= 3600)
|
||||
{
|
||||
[theTime appendFormat:@"%d:",(seconds / 3600)];
|
||||
seconds = seconds % 3600;
|
||||
}
|
||||
|
||||
NSString *elapsedMin = [NSString stringWithFormat:@"%d:",(seconds / 60)];
|
||||
if ([elapsedMin length] == 2)
|
||||
[theTime appendString:[padZero stringByAppendingString:elapsedMin]];
|
||||
else
|
||||
[theTime appendString:elapsedMin];
|
||||
|
||||
seconds = seconds % 60;
|
||||
NSString *elapsedSec = [NSString stringWithFormat:@"%d",seconds];
|
||||
|
||||
if ([elapsedSec length] == 2)
|
||||
[theTime appendString:elapsedSec];
|
||||
else
|
||||
[theTime appendString:[padZero stringByAppendingString:elapsedSec]];
|
||||
|
||||
return theTime;
|
||||
}
|
||||
|
||||
// fuzzy time gives back strings like "about 5 seconds"
|
||||
+ (NSString *)formatFuzzyTime:(int)seconds
|
||||
{
|
||||
// check for seconds first
|
||||
if (seconds < 60) {
|
||||
if (seconds < 7)
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"UnderSec", @"Under %d seconds"), 5];
|
||||
if (seconds < 13)
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"UnderSec", @"Under %d seconds"), 10];
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"UnderMin", @"Under a minute")];
|
||||
}
|
||||
// seconds becomes minutes and we keep checking.
|
||||
seconds = seconds/60;
|
||||
if (seconds < 60) {
|
||||
if (seconds < 2)
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"AboutMin",@"About a minute")];
|
||||
// OK, tell the good people how much time we have left.
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"AboutMins",@"About %d minutes"), seconds];
|
||||
}
|
||||
//this download will never seemingly never end. now seconds become hours.
|
||||
seconds = seconds/60;
|
||||
if (seconds < 2)
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"AboutHour", @"Over an hour")];
|
||||
return [NSString stringWithFormat:NSLocalizedString(@"AboutHours", @"Over %d hours"), seconds];
|
||||
}
|
||||
|
||||
+ (NSString *)formatBytes:(float)bytes
|
||||
{
|
||||
// if bytes are negative, we return question marks.
|
||||
if (bytes < 0)
|
||||
return [NSString stringWithString:@"?"];
|
||||
// bytes first.
|
||||
if (bytes < 1024)
|
||||
return [NSString stringWithFormat:@"%.1f bytes",bytes];
|
||||
// kb
|
||||
bytes = bytes/1024;
|
||||
if (bytes < 1024)
|
||||
return [NSString stringWithFormat:@"%.1f KB",bytes];
|
||||
// mb
|
||||
bytes = bytes/1024;
|
||||
if (bytes < 1024)
|
||||
return [NSString stringWithFormat:@"%.1f MB",bytes];
|
||||
// gb
|
||||
bytes = bytes/1024;
|
||||
return [NSString stringWithFormat:@"%.1f GB",bytes];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
[NSBundle loadNibNamed:@"ProgressView" owner:self];
|
||||
|
||||
[self viewDidLoad];
|
||||
|
||||
// Register for notifications when one of the progress views is expanded/contracted
|
||||
// whilst holding the option button
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(changeCollapsedStateNotification:)
|
||||
name:ProgressViewsShouldResize
|
||||
object:nil];
|
||||
|
||||
[mExpandedRevealButton setEnabled:NO];
|
||||
[mExpandedOpenButton setEnabled:NO];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self
|
||||
name:ProgressViewsShouldResize
|
||||
object:nil];
|
||||
|
||||
// if we get here because we're quitting, the listener will still be alive
|
||||
// yet we're going away. As a result, we need to tell the d/l listener to
|
||||
// forget it ever met us and necko will clean it up on its own.
|
||||
if (mDownloader)
|
||||
mDownloader->DetachDownloadDisplay();
|
||||
NS_IF_RELEASE(mDownloader);
|
||||
|
||||
[mStartTime release];
|
||||
[mSourceURL release];
|
||||
[mDestPath release];
|
||||
[mProgressBar release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// Save the expand/contract view pref (called when the user clicks the dislosure triangle)
|
||||
- (void)setCompactViewPref
|
||||
{
|
||||
[[PreferenceManager sharedInstance] setPref:"browser.download.compactView" toBoolean:mViewIsCompact];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
mViewIsCompact = [[PreferenceManager sharedInstance] getBooleanPref:"browser.download.compactView" withSuccess:NULL];
|
||||
[mProgressBar retain]; // make sure it survives being moved between views
|
||||
|
||||
if (mViewIsCompact)
|
||||
[self moveProgressBarToCurrentView];
|
||||
|
||||
// this isn't necessarily better. Need to profile.
|
||||
[mProgressBar setUsesThreadedAnimation:YES];
|
||||
}
|
||||
|
||||
- (NSView *)view
|
||||
{
|
||||
if (mViewIsCompact)
|
||||
return (mDownloadDone ? mCompletedViewCompact : mProgressViewCompact);
|
||||
else
|
||||
return (mDownloadDone ? mCompletedView : mProgressView);
|
||||
}
|
||||
|
||||
- (IBAction)toggleDisclosure:(id)sender
|
||||
{
|
||||
mViewIsCompact = !mViewIsCompact;
|
||||
|
||||
[self moveProgressBarToCurrentView];
|
||||
|
||||
// Is option/alt held down?
|
||||
if ([[[sender window] currentEvent] modifierFlags] & NSAlternateKeyMask)
|
||||
{
|
||||
// Get all progress views to look the same as self
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:ProgressViewsShouldResize
|
||||
object:[NSNumber numberWithBool:mViewIsCompact]];
|
||||
}
|
||||
|
||||
// Set the pref only when the user clicks the disclosure triangle
|
||||
[self setCompactViewPref];
|
||||
|
||||
// Re-calculate the new view & window sizes
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:StackViewReloadNotificationName
|
||||
object:self];
|
||||
[self refreshDownloadInfo];
|
||||
}
|
||||
|
||||
- (void)changeCollapsedStateNotification:(NSNotification *)notification
|
||||
{
|
||||
// note that this will get called on the view that is being clicked, as well
|
||||
// as the other views. Don't do redundant work here, like redrawing.
|
||||
mViewIsCompact = [[notification object] boolValue];
|
||||
// Don't call [enclosingStackView reloadSubviews]; here, because it will be done
|
||||
// by the original view that was option-clicked, not us
|
||||
}
|
||||
|
||||
-(void)cancel
|
||||
{
|
||||
mUserCancelled = YES;
|
||||
|
||||
if (mDownloader) // we should always have one
|
||||
mDownloader->CancelDownload();
|
||||
|
||||
// clean up downloaded file. - do it here or in CancelDownload?
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
if ([fileManager isDeletableFileAtPath:mDestPath])
|
||||
{
|
||||
// if we delete it, fantastic. if not, oh well. better to move to trash instead?
|
||||
[fileManager removeFileAtPath:mDestPath handler:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)close:(id)sender
|
||||
{
|
||||
if (!mDownloadDone)
|
||||
{
|
||||
mRemoveWhenDone = YES;
|
||||
[self cancel];
|
||||
}
|
||||
else
|
||||
{
|
||||
[mProgressWindowController removeDownload:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)stop:(id)sender
|
||||
{
|
||||
[self cancel];
|
||||
}
|
||||
|
||||
- (IBAction)reveal:(id)sender
|
||||
{
|
||||
if ([[NSWorkspace sharedWorkspace] selectFile:mDestPath
|
||||
inFileViewerRootedAtPath:[mDestPath stringByDeletingLastPathComponent]])
|
||||
return;
|
||||
// hmmm. it didn't work. that's odd. need localized error messages. for now, just beep.
|
||||
NSBeep();
|
||||
}
|
||||
|
||||
- (IBAction)open:(id)sender
|
||||
{
|
||||
if ([[NSWorkspace sharedWorkspace] openFile:mDestPath])
|
||||
return;
|
||||
// hmmm. it didn't work. that's odd. need localized error message. for now, just beep.
|
||||
NSBeep();
|
||||
}
|
||||
|
||||
// Called just before the view will be shown to the user
|
||||
- (void)downloadDidStart
|
||||
{
|
||||
mStartTime = [[NSDate alloc] init];
|
||||
// [mProgressBar startAnimation:self]; // moved to onStartDownload
|
||||
[self refreshDownloadInfo];
|
||||
}
|
||||
|
||||
- (void)downloadDidEnd
|
||||
{
|
||||
mDownloadDone = YES;
|
||||
mDownloadTime = -[mStartTime timeIntervalSinceNow];
|
||||
[mProgressBar stopAnimation:self];
|
||||
|
||||
[mExpandedCancelButton setEnabled:NO];
|
||||
[self refreshDownloadInfo];
|
||||
}
|
||||
|
||||
// this handles lots of things.
|
||||
- (void)refreshDownloadInfo
|
||||
{
|
||||
NSView* curView = [self view];
|
||||
|
||||
NSString* filename = [mSourceURL lastPathComponent];
|
||||
NSString *destPath = [mDestPath stringByAbbreviatingWithTildeInPath];
|
||||
NSString* tooltipFormat = NSLocalizedString(mDownloadDone ? @"DownloadedTooltipFormat" : @"DownloadingTooltipFormat", @"");
|
||||
|
||||
id filenameLabel = [curView viewWithTag:kLabelTagFilename];
|
||||
[filenameLabel setStringValue:filename];
|
||||
[filenameLabel setToolTip:[NSString stringWithFormat:tooltipFormat, [mSourceURL lastPathComponent], mSourceURL, destPath]];
|
||||
|
||||
id destLabel = [curView viewWithTag:kLabelTagDestination];
|
||||
[destLabel setStringValue:destPath];
|
||||
|
||||
id locationLabel = [curView viewWithTag:kLabelTagSource];
|
||||
[locationLabel setStringValue:mSourceURL];
|
||||
|
||||
if (mDownloadDone)
|
||||
{
|
||||
id statusLabel = [curView viewWithTag:kLabelTagStatus];
|
||||
if (statusLabel)
|
||||
{
|
||||
NSString* statusString;
|
||||
if (mUserCancelled)
|
||||
statusString = NSLocalizedString(@"DownloadCancelled", @"Cancelled");
|
||||
else if (mDownloadingError)
|
||||
statusString = NSLocalizedString(@"DownloadInterrupted", @"Interrupted");
|
||||
else
|
||||
statusString = NSLocalizedString(@"DownloadCompleted", @"Completed");
|
||||
|
||||
[statusLabel setStringValue: statusString];
|
||||
}
|
||||
|
||||
// set progress label
|
||||
id progressLabel = [curView viewWithTag:kLabelTagProgress];
|
||||
if (progressLabel)
|
||||
{
|
||||
float byteSec = mCurrentProgress / mDownloadTime;
|
||||
// show how much we downloaded, become some types of disconnects make us think
|
||||
// we finished successfully
|
||||
[progressLabel setStringValue:[NSString stringWithFormat:
|
||||
NSLocalizedString(@"DownloadDoneStatusString", @"%@ of %@ done (at %@/sec)"),
|
||||
[[self class] formatBytes:mCurrentProgress],
|
||||
[[self class] formatBytes:mDownloadSize],
|
||||
[[self class] formatBytes:byteSec]]];
|
||||
}
|
||||
|
||||
id timeLabel = [curView viewWithTag:kLabelTagTimeRemaining];
|
||||
if (timeLabel)
|
||||
[timeLabel setStringValue:[[self class] formatTime:(int)mDownloadTime]];
|
||||
|
||||
id timeLabelLabel = [curView viewWithTag:kLabelTagTimeRemainingLabel];
|
||||
if (timeLabelLabel)
|
||||
[timeLabelLabel setStringValue:NSLocalizedString(@"DownloadRemainingLabelDone", @"Time elapsed:")];
|
||||
|
||||
[self updateButtons];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSTimeInterval elapsedTime = -[mStartTime timeIntervalSinceNow];
|
||||
|
||||
// update status field
|
||||
id progressLabel = [curView viewWithTag:kLabelTagProgress];
|
||||
if (progressLabel)
|
||||
{
|
||||
NSString *statusLabelString = NSLocalizedString(@"DownloadStatusString", @"%@ of %@ total (at %@/sec)");
|
||||
float byteSec = mCurrentProgress / elapsedTime;
|
||||
[progressLabel setStringValue:[NSString stringWithFormat:statusLabelString,
|
||||
[[self class] formatBytes:mCurrentProgress],
|
||||
(mDownloadSize > 0 ? [[self class] formatBytes:mDownloadSize] : @"?"),
|
||||
[[self class] formatBytes:byteSec]]];
|
||||
}
|
||||
|
||||
id timeLabel = [curView viewWithTag:kLabelTagTimeRemaining];
|
||||
if (timeLabel)
|
||||
{
|
||||
if (mDownloadSize > 0)
|
||||
{
|
||||
int secToGo = (int)ceil((elapsedTime * mDownloadSize / mCurrentProgress) - elapsedTime);
|
||||
[timeLabel setStringValue:[[self class] formatFuzzyTime:secToGo]];
|
||||
}
|
||||
else // mDownloadSize is undetermined. Set remaining time to question marks.
|
||||
{
|
||||
NSString *calculatingString = NSLocalizedString(@"DownloadCalculatingString", @"Unknown");
|
||||
[timeLabel setStringValue:calculatingString];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateButtons
|
||||
{
|
||||
// note: this will stat every time, which will be expensive! We could use
|
||||
// FNNotify/FNSubscribe to avoid this (writing a Cocoa wrapper around it).
|
||||
if (mDownloadDone && !mDownloadingError)
|
||||
{
|
||||
BOOL destFileExists = [[NSFileManager defaultManager] fileExistsAtPath:mDestPath];
|
||||
[mExpandedRevealButton setEnabled:destFileExists];
|
||||
[mExpandedOpenButton setEnabled:destFileExists];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)moveProgressBarToCurrentView
|
||||
{
|
||||
[mProgressBar moveToView:(mViewIsCompact ? mProgressViewCompact : mProgressView) resize:YES];
|
||||
[mProgressBar startAnimation:self]; // this is necessary to keep it animating for some reason
|
||||
}
|
||||
|
||||
- (void)setProgressWindowController:(ProgressDlgController*)progressWindowController
|
||||
{
|
||||
mProgressWindowController = progressWindowController;
|
||||
}
|
||||
|
||||
- (BOOL)isActive
|
||||
{
|
||||
return !mDownloadDone;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)onStartDownload:(BOOL)isFileSave
|
||||
{
|
||||
mIsFileSave = isFileSave;
|
||||
[self downloadDidStart];
|
||||
[mProgressWindowController didStartDownload:self];
|
||||
|
||||
// need to do this after the view as been put in the window, otherwise it doesn't work
|
||||
[mProgressBar startAnimation:self];
|
||||
}
|
||||
|
||||
- (void)onEndDownload:(BOOL)completedOK
|
||||
{
|
||||
mDownloadingError = !completedOK;
|
||||
|
||||
[self downloadDidEnd];
|
||||
[mProgressWindowController didEndDownload:self];
|
||||
if (mRemoveWhenDone)
|
||||
[mProgressWindowController removeDownload:self];
|
||||
}
|
||||
|
||||
- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress
|
||||
{
|
||||
mCurrentProgress = aCurProgress; // fall back for stat calcs
|
||||
mDownloadSize = aMaxProgress;
|
||||
|
||||
if (![mProgressBar isIndeterminate]) //most likely - just update value
|
||||
{
|
||||
if (aCurProgress == aMaxProgress) //handles little bug in FTP download size
|
||||
[mProgressBar setMaxValue:aMaxProgress];
|
||||
|
||||
[mProgressBar setDoubleValue:aCurProgress];
|
||||
}
|
||||
else if (aMaxProgress > 0) // ok, we're starting up with good max & cur values
|
||||
{
|
||||
[mProgressBar setIndeterminate:NO];
|
||||
[mProgressBar setMaxValue:aMaxProgress];
|
||||
[mProgressBar setDoubleValue:aCurProgress];
|
||||
} // if neither case was true, it's barber pole city.
|
||||
}
|
||||
|
||||
-(void)setDownloadListener:(CHDownloader*)aDownloader
|
||||
{
|
||||
if (mDownloader != aDownloader)
|
||||
NS_IF_RELEASE(mDownloader);
|
||||
|
||||
NS_IF_ADDREF(mDownloader = aDownloader);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
This is kind of a hack. It should probably be done somewhere else so Mozilla can have
|
||||
it too, but until Apple fixes the problems with the setting of comments without
|
||||
reverting to Applescript, I have left it in.
|
||||
|
||||
Turned off for now, until we find a better way to do this. Won't Carbon APIs work?
|
||||
*/
|
||||
- (void)tryToSetFinderComments
|
||||
{
|
||||
if (mDestPath && mSourceURL)
|
||||
{
|
||||
CFURLRef fileURL = CFURLCreateWithFileSystemPath( NULL,
|
||||
(CFStringRef)mDestPath,
|
||||
kCFURLPOSIXPathStyle,
|
||||
NO);
|
||||
|
||||
NSString *hfsPath = (NSString *)CFURLCopyFileSystemPath(fileURL,
|
||||
kCFURLHFSPathStyle);
|
||||
|
||||
CFRelease(fileURL);
|
||||
|
||||
NSAppleScript *setCommentScript = [[NSAppleScript alloc] initWithSource:
|
||||
[NSString stringWithFormat:@"tell application \"Finder\" to set comment of file \"%@\" to \"%@\"", hfsPath, mSourceURL]];
|
||||
NSDictionary *errorInfo = NULL;
|
||||
|
||||
[setCommentScript executeAndReturnError:&errorInfo];
|
||||
|
||||
if (errorInfo)
|
||||
{
|
||||
NSLog(@"Get error when running AppleScript to set comments for '%@':\n %@",
|
||||
mDestPath,
|
||||
[errorInfo objectForKey:NSAppleScriptErrorMessage]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)setSourceURL:(NSString*)aSourceURL
|
||||
{
|
||||
[mSourceURL autorelease];
|
||||
mSourceURL = [aSourceURL copy];
|
||||
|
||||
//[self tryToSetFinderComments];
|
||||
}
|
||||
|
||||
- (void)setDestinationPath:(NSString*)aDestPath
|
||||
{
|
||||
[mDestPath autorelease];
|
||||
mDestPath = [aDestPath copy];
|
||||
//[self tryToSetFinderComments];
|
||||
}
|
||||
|
||||
@end
|
|
@ -56,7 +56,7 @@ public:
|
|||
nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL,
|
||||
nsIDOMDocument* aDocument, nsIInputStream* aPostData,
|
||||
const nsAString& aSuggestedFilename, PRBool aBypassCache,
|
||||
NSView* aFilterView, NSPopUpButton* aFilterList);
|
||||
NSView* aFilterView);
|
||||
virtual ~nsHeaderSniffer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -79,6 +79,5 @@ private:
|
|||
nsCString mContentType;
|
||||
nsCString mContentDisposition;
|
||||
NSView* mFilterView;
|
||||
NSPopUpButton* mFilterList;
|
||||
};
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
|
||||
#import "NSString+Utils.h"
|
||||
|
||||
#import "ChimeraUIConstants.h"
|
||||
|
||||
#include "SaveHeaderSniffer.h"
|
||||
|
||||
#include "netCore.h"
|
||||
|
@ -56,7 +58,7 @@ const char* const persistContractID = "@mozilla.org/embedding/browser/nsWebBrows
|
|||
nsHeaderSniffer::nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL,
|
||||
nsIDOMDocument* aDocument, nsIInputStream* aPostData,
|
||||
const nsAString& aSuggestedFilename, PRBool aBypassCache,
|
||||
NSView* aFilterView, NSPopUpButton* aFilterList)
|
||||
NSView* aFilterView)
|
||||
: mPersist(aPersist)
|
||||
, mTmpFile(aFile)
|
||||
, mURL(aURL)
|
||||
|
@ -65,9 +67,8 @@ nsHeaderSniffer::nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile,
|
|||
, mDefaultFilename(aSuggestedFilename)
|
||||
, mBypassCache(aBypassCache)
|
||||
, mFilterView(aFilterView)
|
||||
, mFilterList(aFilterList)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
|
||||
nsHeaderSniffer::~nsHeaderSniffer()
|
||||
|
@ -183,14 +184,16 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI)
|
|||
return rv;
|
||||
nsCOMPtr<nsIPrefBranch> dirBranch;
|
||||
prefs->GetBranch("browser.download.", getter_AddRefs(dirBranch));
|
||||
PRInt32 filterIndex = 0;
|
||||
PRInt32 filterIndex = eSaveFormatHTMLComplete;
|
||||
if (dirBranch) {
|
||||
nsresult rv = dirBranch->GetIntPref("save_converter_index", &filterIndex);
|
||||
if (NS_FAILED(rv))
|
||||
filterIndex = 0;
|
||||
filterIndex = eSaveFormatHTMLComplete;
|
||||
}
|
||||
if (mFilterList)
|
||||
[mFilterList selectItemAtIndex: filterIndex];
|
||||
|
||||
NSPopUpButton* filterList = [mFilterView viewWithTag:kSaveFormatPopupTag];
|
||||
if (filterList)
|
||||
[filterList selectItemAtIndex: filterIndex];
|
||||
|
||||
// We need to figure out what file name to use.
|
||||
nsAutoString defaultFileName;
|
||||
|
@ -294,17 +297,17 @@ nsresult nsHeaderSniffer::PerformSave(nsIURI* inOriginalURI)
|
|||
return NS_OK;
|
||||
|
||||
// Update the filter index.
|
||||
if (isHTML && mFilterList) {
|
||||
filterIndex = [mFilterList indexOfSelectedItem];
|
||||
if (isHTML && filterList) {
|
||||
filterIndex = [filterList indexOfSelectedItem];
|
||||
dirBranch->SetIntPref("save_converter_index", filterIndex);
|
||||
}
|
||||
|
||||
// Convert the content type to text/plain if it was selected in the filter.
|
||||
if (isHTML && filterIndex == 2)
|
||||
if (isHTML && filterIndex == eSaveFormatPlainText)
|
||||
mContentType = "text/plain";
|
||||
|
||||
nsCOMPtr<nsISupports> sourceData;
|
||||
if (isHTML && filterIndex != 1)
|
||||
if (isHTML && filterIndex != eSaveFormatHTMLSource)
|
||||
sourceData = do_QueryInterface(mDocument);
|
||||
else
|
||||
sourceData = do_QueryInterface(mURL);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -49,6 +50,8 @@
|
|||
#include "nsIWebBrowserPersist.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsITimer.h"
|
||||
|
||||
#include "nsExternalHelperAppService.h"
|
||||
|
||||
|
||||
|
@ -56,24 +59,28 @@
|
|||
|
||||
class nsDownloadListener : public CHDownloader,
|
||||
public nsIDownload,
|
||||
public nsIWebProgressListener
|
||||
public nsIWebProgressListener,
|
||||
public nsITimerCallback
|
||||
{
|
||||
public:
|
||||
nsDownloadListener(DownloadControllerFactory* inDownloadControllerFactory);
|
||||
nsDownloadListener();
|
||||
virtual ~nsDownloadListener();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOWNLOAD
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
||||
// nsITimerCallback
|
||||
NS_IMETHOD Notify(nsITimer *timer);
|
||||
|
||||
public:
|
||||
//void BeginDownload();
|
||||
|
||||
void InitDialog();
|
||||
|
||||
virtual void PauseDownload();
|
||||
virtual void ResumeDownload();
|
||||
virtual void CancelDownload();
|
||||
virtual void DownloadDone();
|
||||
virtual void DownloadDone(nsresult aStatus);
|
||||
virtual void DetachDownloadDisplay();
|
||||
|
||||
private:
|
||||
|
@ -84,10 +91,13 @@ private:
|
|||
|
||||
nsCOMPtr<nsIURI> mURI; // The URI of our source file. Null if we're saving a complete document.
|
||||
nsCOMPtr<nsILocalFile> mDestination; // Our destination URL.
|
||||
nsCOMPtr<nsITimer> mEndRefreshTimer; // Timer used to update the status to done
|
||||
nsresult mDownloadStatus; // status from last nofication
|
||||
PRInt64 mStartTime; // When the download started
|
||||
PRPackedBool mBypassCache; // Whether we should bypass the cache or not.
|
||||
PRPackedBool mNetworkTransfer; // true if the first OnStateChange has the NETWORK bit set
|
||||
PRPackedBool mGotFirstStateChange; // true after we've seen the first OnStateChange
|
||||
PRPackedBool mUserCanceled; // true if the user canceled the download
|
||||
PRPackedBool mSentCancel; // true when we've notified the backend of the cancel
|
||||
};
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -46,20 +46,25 @@
|
|||
#include "nsIURL.h"
|
||||
#include "netCore.h"
|
||||
|
||||
nsDownloadListener::nsDownloadListener(DownloadControllerFactory* inControllerFactory)
|
||||
: CHDownloader(inControllerFactory)
|
||||
nsDownloadListener::nsDownloadListener()
|
||||
: mDownloadStatus(NS_OK)
|
||||
, mBypassCache(PR_FALSE)
|
||||
, mNetworkTransfer(PR_FALSE)
|
||||
, mGotFirstStateChange(PR_FALSE)
|
||||
, mUserCanceled(PR_FALSE)
|
||||
, mSentCancel(PR_FALSE)
|
||||
{
|
||||
mStartTime = LL_ZERO;
|
||||
}
|
||||
|
||||
nsDownloadListener::~nsDownloadListener()
|
||||
{
|
||||
// if we go away before the timer fires, cancel it
|
||||
if (mEndRefreshTimer)
|
||||
mEndRefreshTimer->Cancel();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED2(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener)
|
||||
NS_IMPL_ISUPPORTS_INHERITED3(nsDownloadListener, CHDownloader, nsIDownload, nsIWebProgressListener, nsITimerCallback)
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
@ -193,14 +198,14 @@ nsDownloadListener::OnProgressChange(nsIWebProgress *aWebProgress,
|
|||
PRInt32 aCurTotalProgress,
|
||||
PRInt32 aMaxTotalProgress)
|
||||
{
|
||||
if (mUserCanceled)
|
||||
if (mUserCanceled && !mSentCancel)
|
||||
{
|
||||
if (mHelperAppLauncher)
|
||||
mHelperAppLauncher->Cancel();
|
||||
else if (aRequest)
|
||||
aRequest->Cancel(NS_BINDING_ABORTED);
|
||||
|
||||
mUserCanceled = false;
|
||||
mSentCancel = PR_TRUE;
|
||||
}
|
||||
|
||||
[mDownloadDisplay setProgressTo:aCurTotalProgress ofMax:aMaxTotalProgress];
|
||||
|
@ -236,7 +241,7 @@ nsDownloadListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *a
|
|||
// Implementation of nsIWebProgressListener
|
||||
/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in unsigned long aStatus); */
|
||||
NS_IMETHODIMP
|
||||
nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags,
|
||||
nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags,
|
||||
PRUint32 aStatus)
|
||||
{
|
||||
// NSLog(@"State changed: state %u, status %u", aStateFlags, aStatus);
|
||||
|
@ -250,29 +255,64 @@ nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRe
|
|||
// the window and controller. We will get this even in the event of a cancel,
|
||||
// so this is the only place in the listener where we should kill the download.
|
||||
if ((aStateFlags & STATE_STOP) && (!mNetworkTransfer || (aStateFlags & STATE_IS_NETWORK))) {
|
||||
DownloadDone();
|
||||
DownloadDone(aStatus);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// nsITimerCallback implementation
|
||||
NS_IMETHODIMP nsDownloadListener::Notify(nsITimer *timer)
|
||||
{
|
||||
// resset the destination, since uniquifying the filename may have
|
||||
// changed it
|
||||
nsAutoString pathStr;
|
||||
mDestination->GetPath(pathStr);
|
||||
[mDownloadDisplay setDestinationPath: [NSString stringWith_nsAString:pathStr]];
|
||||
|
||||
// cancelling should give us a failure status
|
||||
[mDownloadDisplay onEndDownload:(NS_SUCCEEDED(mDownloadStatus) && !mUserCanceled)];
|
||||
mEndRefreshTimer = NULL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
void
|
||||
nsDownloadListener::InitDialog()
|
||||
{
|
||||
// dialog has to be shown before the outlets get hooked up
|
||||
[mDownloadDisplay onStartDownload:(BOOL)IsFileSave()];
|
||||
|
||||
if (mURI)
|
||||
{
|
||||
nsCAutoString spec;
|
||||
mURI->GetSpec(spec);
|
||||
|
||||
// we need to be careful not to show a password in the url
|
||||
nsCAutoString userPassword;
|
||||
mURI->GetUserPass(userPassword);
|
||||
if (!userPassword.IsEmpty())
|
||||
{
|
||||
// ugh, build it by hand
|
||||
nsCAutoString hostport, path;
|
||||
mURI->GetScheme(spec);
|
||||
mURI->GetHostPort(hostport);
|
||||
mURI->GetPath(path);
|
||||
|
||||
spec.Append("://");
|
||||
spec.Append(hostport);
|
||||
spec.Append(path);
|
||||
}
|
||||
else
|
||||
mURI->GetSpec(spec);
|
||||
|
||||
[mDownloadDisplay setSourceURL: [NSString stringWithUTF8String:spec.get()]];
|
||||
}
|
||||
|
||||
nsAutoString pathStr;
|
||||
mDestination->GetPath(pathStr);
|
||||
[mDownloadDisplay setDestinationPath: [NSString stringWith_nsAString:pathStr]];
|
||||
|
||||
[mDownloadDisplay onStartDownload:IsFileSave()];
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -292,19 +332,19 @@ nsDownloadListener::CancelDownload()
|
|||
{
|
||||
mUserCanceled = PR_TRUE;
|
||||
|
||||
if (mWebPersist)
|
||||
if (mWebPersist && !mSentCancel)
|
||||
{
|
||||
mWebPersist->CancelSave();
|
||||
mUserCanceled = PR_FALSE;
|
||||
mSentCancel = PR_TRUE;
|
||||
}
|
||||
|
||||
// delete any files we've created...
|
||||
|
||||
|
||||
// DownloadDone will get called (eventually)
|
||||
}
|
||||
|
||||
void
|
||||
nsDownloadListener::DownloadDone()
|
||||
nsDownloadListener::DownloadDone(nsresult aStatus)
|
||||
{
|
||||
// break the reference cycle by removing ourselves as a listener
|
||||
if (mWebPersist)
|
||||
|
@ -314,8 +354,23 @@ nsDownloadListener::DownloadDone()
|
|||
}
|
||||
|
||||
mHelperAppLauncher = nsnull;
|
||||
|
||||
[mDownloadDisplay onEndDownload];
|
||||
mDownloadStatus = aStatus;
|
||||
|
||||
// hack alert!
|
||||
// Our destination file gets uniquified after the OnStop notification is sent
|
||||
// (in nsExternalAppHandler::ExecuteDesiredAction), so we never get a chance
|
||||
// to figure out the final filename. To work around this, set a timer to fire
|
||||
// in the near future, from which we'll send the done callback.
|
||||
mEndRefreshTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||
if (mEndRefreshTimer)
|
||||
{
|
||||
nsresult rv = mEndRefreshTimer->InitWithCallback(this, 0, nsITimer::TYPE_ONE_SHOT); // defaults to 1-shot, normal priority
|
||||
if (NS_FAILED(rv))
|
||||
mEndRefreshTimer = NULL;
|
||||
}
|
||||
|
||||
if (!mEndRefreshTimer) // timer creation or init failed, so just do it now
|
||||
[mDownloadDisplay onEndDownload:(NS_SUCCEEDED(aStatus) && !mUserCanceled)];
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#import "NSString+Utils.h"
|
||||
|
||||
#import "CHBrowserService.h"
|
||||
#import "CHDownloadFactories.h"
|
||||
#import "CHBrowserView.h"
|
||||
|
||||
#include "nsIWindowWatcher.h"
|
||||
|
@ -107,14 +106,6 @@ CHBrowserService::InitEmbedding()
|
|||
static NS_DEFINE_CID(kHelperDlgCID, NS_HELPERAPPLAUNCHERDIALOG_CID);
|
||||
nsresult rv = cr->RegisterFactory(kHelperDlgCID, NS_IHELPERAPPLAUNCHERDLG_CLASSNAME, NS_IHELPERAPPLAUNCHERDLG_CONTRACTID,
|
||||
sSingleton);
|
||||
|
||||
// replace the downloader with our own which does not rely on the xpfe downlaod manager
|
||||
nsCOMPtr<nsIFactory> downloadFactory;
|
||||
rv = NewDownloadListenerFactory(getter_AddRefs(downloadFactory));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
static NS_DEFINE_CID(kDownloadCID, NS_DOWNLOAD_CID);
|
||||
rv = cr->RegisterFactory(kDownloadCID, "Download", NS_DOWNLOAD_CONTRACTID, downloadFactory);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -163,9 +163,8 @@ enum {
|
|||
// nsIWebBrowserSetup methods
|
||||
- (void)setProperty:(unsigned int)property toValue:(unsigned int)value;
|
||||
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList;
|
||||
- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename;
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView;
|
||||
- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename;
|
||||
|
||||
- (void)printDocument;
|
||||
- (void)pageSetup;
|
||||
|
|
|
@ -430,7 +430,6 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
|||
suggestedFilename: (NSString*)aFileName
|
||||
bypassCache: (BOOL)aBypassCache
|
||||
filterView: (NSView*)aFilterView
|
||||
filterList: (NSPopUpButton*)aFilterList
|
||||
{
|
||||
// Create our web browser persist object. This is the object that knows
|
||||
// how to actually perform the saving of the page (and of the images
|
||||
|
@ -477,7 +476,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
|||
[aFileName assignTo_nsAString:fileName];
|
||||
nsHeaderSniffer* sniffer = new nsHeaderSniffer(webPersist, tmpFile, aURI,
|
||||
aDocument, postData, fileName, aBypassCache,
|
||||
aFilterView, aFilterList);
|
||||
aFilterView);
|
||||
if (!sniffer)
|
||||
return;
|
||||
webPersist->SetProgressListener(sniffer); // owned
|
||||
|
@ -572,8 +571,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
|||
return found;
|
||||
}
|
||||
|
||||
- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename
|
||||
- (void)saveURL: (NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename
|
||||
{
|
||||
nsCOMPtr<nsIURI> url;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(url), [aURLSpec UTF8String]);
|
||||
|
@ -584,8 +582,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
|||
withDocument: nsnull
|
||||
suggestedFilename: aFilename
|
||||
bypassCache: YES
|
||||
filterView: aFilterView
|
||||
filterList: aFilterList];
|
||||
filterView: aFilterView];
|
||||
}
|
||||
|
||||
-(NSString*)getFocusedURLString
|
||||
|
@ -616,7 +613,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
|||
return [NSString stringWith_nsAString: urlStr];
|
||||
}
|
||||
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView
|
||||
{
|
||||
if (!_webBrowser)
|
||||
return;
|
||||
|
@ -656,8 +653,7 @@ const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
|||
withDocument: domDocument
|
||||
suggestedFilename: @""
|
||||
bypassCache: NO
|
||||
filterView: aFilterView
|
||||
filterList: aFilterList];
|
||||
filterView: aFilterView];
|
||||
}
|
||||
|
||||
-(void)doCommand:(const char*)commandName
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -45,19 +46,17 @@
|
|||
1. The CHDownloadProgressDisplay protocol.
|
||||
|
||||
This is a formal protocol that needs to be implemented by
|
||||
a window controller for your progress window. Its methods
|
||||
will be called by the underlying C++ downloading classes.
|
||||
an object (eg. a window controller or a view controller)
|
||||
for your progress window. Its methods will be called by the
|
||||
underlying C++ downloading classes.
|
||||
|
||||
2. The Obj-C DownloadControllerFactory class.
|
||||
|
||||
This class should be subclassed by an embedder, with an
|
||||
implementation of 'createDownloadController' that hands back
|
||||
a new instance of an NSWindowController that implements the
|
||||
<CHDownloadProgressDisplay> protocol.
|
||||
|
||||
The underlying C++ classes use this factory to create the
|
||||
progress window controller.
|
||||
2. The CHDownloadDisplayFactory protocol
|
||||
|
||||
This is a formal protocol that can be implemented by
|
||||
any object that can create objects that themselves
|
||||
implement CHDownloadProgressDisplay. This would probably be
|
||||
an NSWindowController.
|
||||
|
||||
3. The CHDownloader C++ class
|
||||
|
||||
This base class exists to hide the complextity of the download
|
||||
|
@ -90,10 +89,10 @@
|
|||
|
||||
In both cases, creating the nsDownloadListener and calling its Init() method
|
||||
calls nsDownloder::CreateDownloadDisplay(). The nsDownloder has as a member
|
||||
variable a DownloadControllerFactory (see above), which got passed to it
|
||||
via our XPCOM factory for nsIDownload objects. It then uses that DownloadControllerFactory
|
||||
to get an instance of the download progress window controller, which then
|
||||
shows the download progress window.
|
||||
variable an object that implements CHDownloadDisplayFactory (see above), which got set
|
||||
on it via a call to SetDisplayFactory. It then uses that CHDownloadDisplayFactory
|
||||
to create an instance of the download progress display, which then controls
|
||||
something (like a view or window) that shows in the UI.
|
||||
|
||||
Simple, eh?
|
||||
|
||||
|
@ -105,13 +104,13 @@
|
|||
|
||||
class CHDownloader;
|
||||
|
||||
// a formal protocol for something that implements progress display
|
||||
// Embedders can make a window controller that conforms to this
|
||||
// A formal protocol for something that implements progress display.
|
||||
// Embedders can make a window or view controller that conforms to this
|
||||
// protocol, and reuse nsDownloadListener to get download UI.
|
||||
@protocol CHDownloadProgressDisplay
|
||||
|
||||
- (void)onStartDownload:(BOOL)isFileSave;
|
||||
- (void)onEndDownload;
|
||||
- (void)onEndDownload:(BOOL)completedOK;
|
||||
|
||||
- (void)setProgressTo:(long)aCurProgress ofMax:(long)aMaxProgress;
|
||||
|
||||
|
@ -121,35 +120,34 @@ class CHDownloader;
|
|||
|
||||
@end
|
||||
|
||||
// subclass this, and have your subclass instantiate and return your window
|
||||
// controller in createDownloadController
|
||||
@interface DownloadControllerFactory : NSObject
|
||||
{
|
||||
}
|
||||
// A formal protocol which is implemented by a factory of progress UI.
|
||||
@protocol CHDownloadDisplayFactory
|
||||
|
||||
- (NSWindowController<CHDownloadProgressDisplay> *)createDownloadController;
|
||||
- (id <CHDownloadProgressDisplay>)createProgressDisplay;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
// Pure virtual base class for a generic downloader, that the progress UI can talk to.
|
||||
// It implements nsISupports so that it can be refcounted. This class insulates the
|
||||
// UI code from having to know too much about the nsIDownloadListener.
|
||||
// It is responsible for creating the download UI, via the DownloadControllerFactory
|
||||
// UI code from having to know too much about the nsDownloadListener.
|
||||
// It is responsible for creating the download UI, via the CHDownloadController
|
||||
// that it owns.
|
||||
class CHDownloader : public nsISupports
|
||||
{
|
||||
public:
|
||||
CHDownloader(DownloadControllerFactory* inControllerFactory);
|
||||
CHDownloader();
|
||||
virtual ~CHDownloader();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual void SetDisplayFactory(id<CHDownloadDisplayFactory> inDownloadDisplayFactory); // retains
|
||||
|
||||
virtual void PauseDownload() = 0;
|
||||
virtual void ResumeDownload() = 0;
|
||||
virtual void CancelDownload() = 0;
|
||||
virtual void DownloadDone() = 0;
|
||||
virtual void DetachDownloadDisplay() = 0; // tell downloader to forget about its display
|
||||
virtual void DownloadDone(nsresult aStatus) = 0;
|
||||
virtual void DetachDownloadDisplay() = 0; // tell downloader to forget about its display
|
||||
|
||||
virtual void CreateDownloadDisplay();
|
||||
|
||||
|
@ -160,8 +158,8 @@ protected:
|
|||
|
||||
protected:
|
||||
|
||||
DownloadControllerFactory* mControllerFactory;
|
||||
id <CHDownloadProgressDisplay> mDownloadDisplay; // something that implements the CHDownloadProgressDisplay protocol
|
||||
PRBool mIsFileSave; // true if we're doing a save, rather than a download
|
||||
id<CHDownloadDisplayFactory> mDisplayFactory;
|
||||
id<CHDownloadProgressDisplay> mDownloadDisplay; // something that implements the CHDownloadProgressDisplay protocol
|
||||
PRBool mIsFileSave; // true if we're doing a save, rather than a download
|
||||
};
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -37,40 +38,34 @@
|
|||
|
||||
#import "CHDownloadProgressDisplay.h"
|
||||
|
||||
// CHDownloader is a simple class that that the download UI can talk to
|
||||
|
||||
@implementation DownloadControllerFactory
|
||||
|
||||
- (NSWindowController<CHDownloadProgressDisplay> *)createDownloadController
|
||||
{
|
||||
// a dummy implementation. You should provide a subclass that
|
||||
// returns an instance of your progress dialog controller.
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// see the header file for comments
|
||||
CHDownloader::CHDownloader(DownloadControllerFactory* inControllerFactory)
|
||||
: mControllerFactory(inControllerFactory)
|
||||
CHDownloader::CHDownloader()
|
||||
: mDisplayFactory(NULL)
|
||||
, mDownloadDisplay(nil)
|
||||
, mIsFileSave(PR_FALSE)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
[mControllerFactory retain];
|
||||
}
|
||||
|
||||
CHDownloader::~CHDownloader()
|
||||
{
|
||||
[mControllerFactory release];
|
||||
[mDisplayFactory release];
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(CHDownloader, nsISupports);
|
||||
|
||||
void
|
||||
CHDownloader::SetDisplayFactory(id<CHDownloadDisplayFactory> inDownloadControllerFactory)
|
||||
{
|
||||
mDisplayFactory = inDownloadControllerFactory;
|
||||
[mDisplayFactory retain];
|
||||
}
|
||||
|
||||
void
|
||||
CHDownloader::CreateDownloadDisplay()
|
||||
{
|
||||
mDownloadDisplay = [mControllerFactory createDownloadController];
|
||||
NS_ASSERTION(mDisplayFactory, "Should have a UI factory");
|
||||
mDownloadDisplay = [mDisplayFactory createProgressDisplay];
|
||||
[mDownloadDisplay setDownloadListener:this];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Chimera code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Calum Robinson.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
// views contained in the stack should send this notification when they change size
|
||||
extern NSString* StackViewReloadNotificationName;
|
||||
|
||||
// the stack view sends this notification after it has adjusted to subview sizes
|
||||
extern NSString* StackViewResizedNotificationName;
|
||||
|
||||
@interface CHStackView : NSView
|
||||
{
|
||||
IBOutlet id mDataSource;
|
||||
}
|
||||
|
||||
- (void)setDataSource:(id)aDataSource;
|
||||
- (void)reloadSubviews;
|
||||
|
||||
@end
|
||||
|
||||
@protocol CHStackViewDataSource
|
||||
|
||||
- (int)subviewsForStackView:(CHStackView *)stackView;
|
||||
- (NSView *)viewForStackView:(CHStackView *)stackView atIndex:(int)index;
|
||||
|
||||
@end
|
|
@ -0,0 +1,143 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Chimera code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Calum Robinson.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Calum Robinson <calumr@mac.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/*
|
||||
This class was inspired by the OAStack view from OmniGroup, but not copied directly. This
|
||||
implementation is a little simpler, which is fine.
|
||||
|
||||
It's like NSTableView, except the data source returns views instead of strings/images etc.
|
||||
*/
|
||||
|
||||
#import "CHStackView.h"
|
||||
|
||||
NSString* StackViewReloadNotificationName = @"ReloadStackView";
|
||||
NSString* StackViewResizedNotificationName = @"StackViewResized";
|
||||
|
||||
@implementation CHStackView
|
||||
|
||||
- (id)initWithFrame:(NSRect)frameRect
|
||||
{
|
||||
if ((self = [super initWithFrame:frameRect]))
|
||||
{
|
||||
// Register for notifications when one of the subviews changes size
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(reloadNotification:)
|
||||
name:StackViewReloadNotificationName
|
||||
object:nil];
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)setDataSource:(id)aDataSource
|
||||
{
|
||||
mDataSource = aDataSource; // should this retain?
|
||||
|
||||
[self reloadSubviews];
|
||||
}
|
||||
|
||||
- (void)reloadNotification:(NSNotification *)notification
|
||||
{
|
||||
[self reloadSubviews];
|
||||
}
|
||||
|
||||
- (void)reloadSubviews
|
||||
{
|
||||
NSRect newFrame = [self frame];
|
||||
NSSize oldSize = [self bounds].size;
|
||||
int i, subviewCount = [mDataSource subviewsForStackView:self];
|
||||
|
||||
NSPoint nextOrigin = NSZeroPoint;
|
||||
|
||||
// we'll maintain the width of the stack view, assuming that it's
|
||||
// scaled by its superview.
|
||||
newFrame.size.height = 0.0;
|
||||
|
||||
[[self subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
|
||||
|
||||
for (i = 0; i < subviewCount; i++)
|
||||
{
|
||||
NSView *subview = [mDataSource viewForStackView:self atIndex:i];
|
||||
NSRect subviewFrame = [subview frame];
|
||||
|
||||
unsigned int autoResizeMask = [subview autoresizingMask];
|
||||
if (autoResizeMask & NSViewWidthSizable)
|
||||
subviewFrame.size.width = newFrame.size.width;
|
||||
|
||||
newFrame.size.height += NSHeight(subviewFrame);
|
||||
|
||||
subviewFrame.origin = nextOrigin;
|
||||
[subview setFrame:subviewFrame];
|
||||
nextOrigin.y += NSHeight(subviewFrame);
|
||||
|
||||
[self addSubview:subview];
|
||||
|
||||
// If there are more subviews, add a separator
|
||||
if (i + 1 < subviewCount)
|
||||
{
|
||||
NSBox *separator = [[NSBox alloc] initWithFrame:
|
||||
NSMakeRect(nextOrigin.x, nextOrigin.y - 1.0, NSWidth([subview frame]), 1.0)];
|
||||
[separator setBoxType:NSBoxSeparator];
|
||||
[separator setAutoresizingMask:NSViewWidthSizable];
|
||||
[self addSubview:separator];
|
||||
[separator release];
|
||||
}
|
||||
}
|
||||
|
||||
NSRect newBounds = newFrame;
|
||||
newBounds.origin = NSZeroPoint;
|
||||
|
||||
[self setFrame:newFrame];
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:StackViewResizedNotificationName
|
||||
object:self
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSValue valueWithSize:oldSize], @"oldsize", nil]];
|
||||
}
|
||||
|
||||
- (BOOL)isFlipped
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
|
@ -0,0 +1,60 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Chimera code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// utility routine; returns YES if the sizes are equal, with the given slop
|
||||
BOOL CHCloseSizes(NSSize aSize, NSSize bSize, float slop);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// category on NSView to add utilities for easy view resizing etc.
|
||||
|
||||
@interface NSView(CHViewUtils)
|
||||
|
||||
// move the recipient view from its superview to the destView,
|
||||
// maintaining the relative size and position of the view based
|
||||
// on its autoresize flags.
|
||||
- (void)moveToView:(NSView*)destView resize:(BOOL)resize;
|
||||
|
||||
@end
|
|
@ -0,0 +1,154 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Chimera code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "NSView+Utils.h"
|
||||
|
||||
BOOL CHCloseSizes(NSSize aSize, NSSize bSize, float slop)
|
||||
{
|
||||
return (fabs(aSize.width - bSize.width) <= slop) &&
|
||||
(fabs(aSize.height - bSize.height) <= slop);
|
||||
}
|
||||
|
||||
// mask has 3 bits: 0 = 1 scales, 1 = 2 scales, 2 = 3 scales.
|
||||
static void RedistributeSpace(int resizeMask, float newWidth, /* in out */ float ioSpaces[3])
|
||||
{
|
||||
float oldWidth = ioSpaces[0] + ioSpaces[1] + ioSpaces[2];
|
||||
|
||||
if (resizeMask != 0)
|
||||
{
|
||||
switch (resizeMask)
|
||||
{
|
||||
// 1 scalable section
|
||||
case 1: // first
|
||||
ioSpaces[0] += newWidth - oldWidth; // it can go negative
|
||||
break;
|
||||
case 2: // middle
|
||||
ioSpaces[1] += newWidth - oldWidth; // it can go negative
|
||||
break;
|
||||
case 4: // last
|
||||
ioSpaces[2] += newWidth - oldWidth; // it can go negative
|
||||
break;
|
||||
|
||||
// 2 scalable sections
|
||||
case 3: // last fixed
|
||||
{
|
||||
float oldScaledWidth = ioSpaces[0] + ioSpaces[1];
|
||||
float newScaledWidth = (newWidth - ioSpaces[2]);
|
||||
ioSpaces[0] = newScaledWidth * (ioSpaces[0] / oldScaledWidth);
|
||||
ioSpaces[1] = newScaledWidth * (ioSpaces[1] / oldScaledWidth);
|
||||
break;
|
||||
}
|
||||
case 5: // middle fixed
|
||||
{
|
||||
float oldScaledWidth = ioSpaces[0] + ioSpaces[2];
|
||||
float newScaledWidth = (newWidth - ioSpaces[1]);
|
||||
ioSpaces[0] = newScaledWidth * (ioSpaces[0] / oldScaledWidth);
|
||||
ioSpaces[2] = newScaledWidth * (ioSpaces[2] / oldScaledWidth);
|
||||
break;
|
||||
}
|
||||
case 6: // first fixed
|
||||
{
|
||||
float oldScaledWidth = ioSpaces[1] + ioSpaces[2];
|
||||
float newScaledWidth = (newWidth - ioSpaces[0]);
|
||||
ioSpaces[1] = newScaledWidth * (ioSpaces[1] / oldScaledWidth);
|
||||
ioSpaces[2] = newScaledWidth * (ioSpaces[2] / oldScaledWidth);
|
||||
break;
|
||||
}
|
||||
|
||||
// all scalable
|
||||
case 7:
|
||||
ioSpaces[0] *= newWidth / oldWidth;
|
||||
ioSpaces[1] *= newWidth / oldWidth;
|
||||
ioSpaces[2] *= newWidth / oldWidth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// otherwise nothing changes
|
||||
}
|
||||
|
||||
@implementation NSView(CHViewUtils)
|
||||
|
||||
- (void)moveToView:(NSView*)destView resize:(BOOL)resize
|
||||
{
|
||||
//resize &= [destView autoresizesSubviews];
|
||||
|
||||
NSRect oldFrame = [self frame];
|
||||
NSRect oldSuperBounds = [[self superview] bounds];
|
||||
|
||||
[self retain];
|
||||
[self removeFromSuperview];
|
||||
|
||||
[destView addSubview:self];
|
||||
[self release];
|
||||
|
||||
[destView setAutoresizesSubviews:YES];
|
||||
|
||||
if (resize)
|
||||
{
|
||||
unsigned int resizeMask = [self autoresizingMask];
|
||||
NSRect newFrame = oldFrame;
|
||||
|
||||
if (resizeMask != NSViewNotSizable && !NSEqualRects([destView bounds], oldSuperBounds))
|
||||
{
|
||||
float spaces[3];
|
||||
// horizontal
|
||||
float newWidth = NSWidth([destView bounds]);
|
||||
spaces[0] = NSMinX(oldFrame);
|
||||
spaces[1] = NSWidth(oldFrame);
|
||||
spaces[2] = NSMaxX(oldSuperBounds) - NSMaxX(oldFrame);
|
||||
|
||||
RedistributeSpace(resizeMask & 0x07, newWidth, spaces);
|
||||
newFrame.origin.x = spaces[0];
|
||||
newFrame.size.width = spaces[1];
|
||||
|
||||
// vertical. we assume that the view should stick to the top of the destView here
|
||||
float newHeight = NSHeight([destView bounds]);
|
||||
spaces[0] = NSMinY(oldFrame);
|
||||
spaces[1] = NSHeight(oldFrame);
|
||||
spaces[2] = NSMaxY(oldSuperBounds) - NSMaxY(oldFrame);
|
||||
|
||||
RedistributeSpace((resizeMask >> 3) & 0x07, newHeight, spaces);
|
||||
newFrame.origin.y = spaces[0];
|
||||
newFrame.size.height = spaces[1];
|
||||
}
|
||||
|
||||
[self setFrame:newFrame];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -51,24 +51,31 @@ class nsIRDFService;
|
|||
@interface RDFOutlineViewItem : NSObject
|
||||
{
|
||||
nsIRDFResource* mResource;
|
||||
unsigned int mCacheVersion; // if matches the cache version in the data source,
|
||||
// cached values are valid
|
||||
BOOL mExpandable;
|
||||
int mNumChildren;
|
||||
NSArray* mChildNodes;
|
||||
}
|
||||
|
||||
- (nsIRDFResource*) resource;
|
||||
- (void) setResource: (nsIRDFResource*) aResource;
|
||||
- (nsIRDFResource*)resource; // addRefs the result
|
||||
- (void)setResource:(nsIRDFResource*) aResource;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface RDFOutlineViewDataSource : NSObject {
|
||||
nsIRDFDataSource* mDataSource;
|
||||
nsIRDFContainer* mContainer;
|
||||
nsIRDFContainerUtils* mContainerUtils;
|
||||
nsIRDFResource* mRootResource;
|
||||
nsIRDFService* mRDFService;
|
||||
@interface RDFOutlineViewDataSource : NSObject
|
||||
{
|
||||
nsIRDFDataSource* mDataSource;
|
||||
nsIRDFContainer* mContainer;
|
||||
nsIRDFContainerUtils* mContainerUtils;
|
||||
nsIRDFResource* mRootResource;
|
||||
nsIRDFService* mRDFService;
|
||||
|
||||
IBOutlet ExtendedOutlineView* mOutlineView;
|
||||
IBOutlet ExtendedOutlineView* mOutlineView;
|
||||
|
||||
NSMutableDictionary* mDictionary;
|
||||
NSMutableDictionary* mDictionary;
|
||||
unsigned int mCacheVersion;
|
||||
}
|
||||
|
||||
// Initialization Methods
|
||||
|
@ -85,7 +92,6 @@ class nsIRDFService;
|
|||
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item;
|
||||
- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item;
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item;
|
||||
|
||||
// tooltip support from the ExtendedOutlineView. Override to provide a tooltip
|
||||
// other than the Name property for each item in the view.
|
||||
|
@ -94,14 +100,14 @@ class nsIRDFService;
|
|||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren;
|
||||
|
||||
// Implementation Methods
|
||||
- (id) makeWrapperFor: (nsIRDFResource*) aRDFResource;
|
||||
- (id)getWrapperFor:(nsIRDFResource*) aRDFResource;
|
||||
- (void)invalidateCachedItems;
|
||||
|
||||
// override to do something different with the cell data rather than just
|
||||
// return a string (add an icon in an attributed string, for example).
|
||||
-(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem;
|
||||
- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem;
|
||||
|
||||
-(void) getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem
|
||||
result:(PRUnichar**)outResult;
|
||||
- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#import "RDFOutlineViewDataSource.h"
|
||||
#import "CHBrowserService.h"
|
||||
|
||||
#include "nsCRT.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIRDFLiteral.h"
|
||||
|
@ -55,14 +56,116 @@
|
|||
#include "nsXPIDLString.h"
|
||||
#include "nsString.h"
|
||||
|
||||
@interface RDFOutlineViewDataSource(Private);
|
||||
|
||||
- (void)registerForShutdownNotification;
|
||||
- (void)cleanup;
|
||||
@interface RDFOutlineViewItem(Private)
|
||||
|
||||
- (unsigned int)cacheVersion;
|
||||
- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version;
|
||||
- (void)setChildren:(NSArray*)childArray;
|
||||
- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren;
|
||||
- (BOOL)cachedChildren;
|
||||
|
||||
- (BOOL)isExpandable;
|
||||
- (int)numChildren;
|
||||
- (id)childAtIndex:(int)index;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation RDFOutlineViewItem
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
mCacheVersion = 0;
|
||||
mExpandable = NO;
|
||||
mNumChildren = 0;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[mChildNodes release];
|
||||
NS_IF_RELEASE(mResource);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (nsIRDFResource*)resource
|
||||
{
|
||||
NS_IF_ADDREF(mResource);
|
||||
return mResource;
|
||||
}
|
||||
|
||||
- (void)setResource:(nsIRDFResource*) aResource
|
||||
{
|
||||
nsIRDFResource* oldResource = mResource;
|
||||
NS_IF_ADDREF(mResource = aResource);
|
||||
NS_IF_RELEASE(oldResource);
|
||||
}
|
||||
|
||||
- (unsigned int)cacheVersion
|
||||
{
|
||||
return mCacheVersion;
|
||||
}
|
||||
|
||||
- (void)setNumChildren:(int)numChildren isExpandable:(BOOL)expandable cacheVersion:(unsigned int)version;
|
||||
{
|
||||
mNumChildren = numChildren;
|
||||
mExpandable = expandable;
|
||||
mCacheVersion = version;
|
||||
}
|
||||
|
||||
- (void)setChildren:(NSArray*)childArray
|
||||
{
|
||||
// childArray can legally be nil here. If it is, we're clearing the cached children
|
||||
NSArray* oldChildren = mChildNodes;
|
||||
mChildNodes = childArray;
|
||||
[mChildNodes retain];
|
||||
[oldChildren release];
|
||||
}
|
||||
|
||||
- (BOOL)cacheValid:(unsigned int)version needChildren:(BOOL)needChildren;
|
||||
{
|
||||
return (mCacheVersion == version) && (needChildren ? (mChildNodes != nil) : 1);
|
||||
}
|
||||
|
||||
- (BOOL)cachedChildren
|
||||
{
|
||||
return (mChildNodes != nil);
|
||||
}
|
||||
|
||||
- (BOOL)isExpandable
|
||||
{
|
||||
return mExpandable;
|
||||
}
|
||||
|
||||
- (int)numChildren
|
||||
{
|
||||
return mNumChildren;
|
||||
}
|
||||
|
||||
- (id)childAtIndex:(int)index
|
||||
{
|
||||
if (mChildNodes)
|
||||
return [mChildNodes objectAtIndex:index];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark -
|
||||
|
||||
@interface RDFOutlineViewDataSource(Private)
|
||||
|
||||
- (void)registerForShutdownNotification;
|
||||
- (void)cleanup;
|
||||
- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RDFOutlineViewDataSource
|
||||
|
||||
- (id)init
|
||||
|
@ -70,6 +173,7 @@
|
|||
if ((self = [super init]))
|
||||
{
|
||||
[self registerForShutdownNotification];
|
||||
mCacheVersion = 1;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -78,7 +182,7 @@
|
|||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
[self cleanup];
|
||||
[self cleanup];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -167,123 +271,62 @@
|
|||
// XXX - For now, we'll just say that none of our items are editable, as we aren't using any
|
||||
// RDF datasources that are mutable.
|
||||
//
|
||||
- (BOOL) outlineView: (NSOutlineView*) aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn
|
||||
- (BOOL) outlineView: (NSOutlineView*)aOutlineView shouldEditTableColumn: (NSTableColumn*) aTableColumn
|
||||
item: (id) aItem
|
||||
{
|
||||
return NO;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL) outlineView: (NSOutlineView*) aOutlineView isItemExpandable: (id) aItem
|
||||
- (BOOL) outlineView: (NSOutlineView*)aOutlineView isItemExpandable:(id)aItem
|
||||
{
|
||||
if (!mDataSource)
|
||||
return NO;
|
||||
|
||||
if (!aItem)
|
||||
return YES; // The root is always open
|
||||
|
||||
nsCOMPtr<nsIRDFResource> itemResource = dont_AddRef([aItem resource]);
|
||||
|
||||
PRBool isSeq = PR_FALSE;
|
||||
mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq);
|
||||
if (isSeq)
|
||||
return YES;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childProperty;
|
||||
mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty));
|
||||
|
||||
nsCOMPtr<nsIRDFNode> childNode;
|
||||
mDataSource->GetTarget(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNode));
|
||||
|
||||
return childNode != nsnull;
|
||||
if (!mDataSource)
|
||||
return NO;
|
||||
|
||||
if (!aItem)
|
||||
return YES; // The root is always open
|
||||
|
||||
if (![aItem cacheValid:mCacheVersion needChildren:NO])
|
||||
[self updateItemProperties:aItem enumerateChildren:NO];
|
||||
|
||||
return [aItem isExpandable];
|
||||
}
|
||||
|
||||
- (id) outlineView: (NSOutlineView*) aOutlineView child: (int) aIndex
|
||||
ofItem: (id) aItem
|
||||
- (id)outlineView:(NSOutlineView*)aOutlineView child:(int)aIndex ofItem:(id)aItem
|
||||
{
|
||||
if (!mDataSource)
|
||||
return nil;
|
||||
if (!mDataSource)
|
||||
return nil;
|
||||
|
||||
if (!aItem)
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> rootResource = dont_AddRef([self rootResource]);
|
||||
aItem = [self getWrapperFor:rootResource];
|
||||
}
|
||||
|
||||
if (![aItem cacheValid:mCacheVersion needChildren:YES])
|
||||
[self updateItemProperties:aItem enumerateChildren:YES];
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource = !aItem ? dont_AddRef([self rootResource]) : dont_AddRef([aItem resource]);
|
||||
|
||||
nsCOMPtr<nsIRDFResource> ordinalResource;
|
||||
mContainerUtils->IndexToOrdinalResource(aIndex + 1, getter_AddRefs(ordinalResource));
|
||||
|
||||
nsCOMPtr<nsIRDFNode> childNode;
|
||||
mDataSource->GetTarget(resource, ordinalResource, PR_TRUE, getter_AddRefs(childNode));
|
||||
if (childNode) {
|
||||
// Yay. A regular container. We don't need to count, we can go directly to
|
||||
// our object.
|
||||
nsCOMPtr<nsIRDFResource> childResource(do_QueryInterface(childNode));
|
||||
if (childResource)
|
||||
return [self makeWrapperFor:childResource];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Oh well, not a regular container. We need to count, dagnabbit.
|
||||
nsCOMPtr<nsIRDFResource> childProperty;
|
||||
mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty));
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> childNodes;
|
||||
mDataSource->GetTargets(resource, childProperty, PR_TRUE, getter_AddRefs(childNodes));
|
||||
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
PRInt32 count = 0;
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
childNodes->GetNext(getter_AddRefs(supp));
|
||||
if (count == aIndex)
|
||||
break;
|
||||
count ++;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childResource(do_QueryInterface(supp));
|
||||
if (childResource) {
|
||||
return [self makeWrapperFor:childResource];
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
return [aItem childAtIndex:aIndex];
|
||||
}
|
||||
|
||||
- (int) outlineView: (NSOutlineView*) aOutlineView numberOfChildrenOfItem: (id) aItem;
|
||||
- (int)outlineView:(NSOutlineView*)aOutlineView numberOfChildrenOfItem:(id) aItem;
|
||||
{
|
||||
if (!mDataSource)
|
||||
return 0;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource = dont_AddRef(aItem ? [aItem resource] : [self rootResource]);
|
||||
|
||||
// XXX just assume NC:child is the only containment arc for now
|
||||
nsCOMPtr<nsIRDFResource> childProperty;
|
||||
mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty));
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> childNodes;
|
||||
mDataSource->GetTargets(resource, childProperty, PR_TRUE, getter_AddRefs(childNodes));
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
PRInt32 count = 0;
|
||||
|
||||
while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
childNodes->GetNext(getter_AddRefs(supp));
|
||||
count ++;
|
||||
}
|
||||
|
||||
if (count == 0) {
|
||||
nsresult rv = mContainer->Init(mDataSource, resource);
|
||||
if (NS_FAILED(rv))
|
||||
return 0;
|
||||
|
||||
mContainer->GetCount(&count);
|
||||
}
|
||||
|
||||
return count;
|
||||
if (!mDataSource)
|
||||
return 0;
|
||||
|
||||
if (!aItem)
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> rootResource = dont_AddRef([self rootResource]);
|
||||
aItem = [self getWrapperFor:rootResource];
|
||||
}
|
||||
|
||||
if (![aItem cacheValid:mCacheVersion needChildren:YES])
|
||||
[self updateItemProperties:aItem enumerateChildren:YES];
|
||||
|
||||
return [aItem numChildren];
|
||||
}
|
||||
|
||||
- (id) outlineView: (NSOutlineView*) aOutlineView objectValueForTableColumn: (NSTableColumn*) aTableColumn
|
||||
byItem: (id) aItem
|
||||
- (id)outlineView:(NSOutlineView*)aOutlineView objectValueForTableColumn:(NSTableColumn*)aTableColumn
|
||||
byItem:(id)aItem
|
||||
{
|
||||
if (!mDataSource || !aItem)
|
||||
return nil;
|
||||
|
@ -291,25 +334,22 @@
|
|||
// The table column's identifier is the RDF Resource URI of the property being displayed in
|
||||
// that column, e.g. "http://home.netscape.com/NC-rdf#Name"
|
||||
NSString* columnPropertyURI = [aTableColumn identifier];
|
||||
nsXPIDLString literalValue;
|
||||
[self getPropertyString:columnPropertyURI forItem:aItem result:getter_Copies(literalValue)];
|
||||
NSString* propString = [self getPropertyString:columnPropertyURI forItem:aItem];
|
||||
|
||||
return [self createCellContents:literalValue withColumn:columnPropertyURI byItem:aItem];
|
||||
return [self createCellContents:propString withColumn:columnPropertyURI byItem:aItem];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// createCellContents:withColumn:byItem
|
||||
//
|
||||
// Constructs a NSString from the given string data for this item in the given column.
|
||||
// This should be overridden to do more fancy things, such as add an icon, etc.
|
||||
//
|
||||
-(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem
|
||||
- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id)inItem
|
||||
{
|
||||
return [NSString stringWith_nsAString: inValue];
|
||||
return inValue;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// outlineView:tooltipForString
|
||||
//
|
||||
|
@ -318,21 +358,9 @@
|
|||
//
|
||||
- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem
|
||||
{
|
||||
nsXPIDLString literalValue;
|
||||
[self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem result:getter_Copies(literalValue)];
|
||||
return [NSString stringWith_nsAString:literalValue];
|
||||
return [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:inItem];
|
||||
}
|
||||
|
||||
|
||||
- (void) outlineView: (NSOutlineView*) aOutlineView setObjectValue: (id) aObject
|
||||
forTableColumn: (NSTableColumn*) aTableColumn
|
||||
byItem: (id) aItem
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void) reloadDataForItem: (id) aItem reloadChildren: (BOOL) aReloadChildren
|
||||
{
|
||||
if (!aItem)
|
||||
|
@ -341,7 +369,7 @@
|
|||
[mOutlineView reloadItem: aItem reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (id) makeWrapperFor: (nsIRDFResource*) aRDFResource
|
||||
- (id)getWrapperFor:(nsIRDFResource*) aRDFResource
|
||||
{
|
||||
const char* k;
|
||||
aRDFResource->GetValueConst(&k);
|
||||
|
@ -350,8 +378,9 @@
|
|||
// see if we've created a wrapper already, if not, create a new wrapper object
|
||||
// and stash it in our dictionary
|
||||
RDFOutlineViewItem* item = [mDictionary objectForKey:key];
|
||||
if (!item) {
|
||||
item = [[RDFOutlineViewItem alloc] init];
|
||||
if (!item)
|
||||
{
|
||||
item = [[[RDFOutlineViewItem alloc] init] autorelease];
|
||||
[item setResource: aRDFResource];
|
||||
[mDictionary setObject:item forKey:key]; // retains |item|
|
||||
}
|
||||
|
@ -359,14 +388,56 @@
|
|||
return item;
|
||||
}
|
||||
|
||||
|
||||
-(void) getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem
|
||||
result:(PRUnichar**)outResult
|
||||
- (void)invalidateCachedItems
|
||||
{
|
||||
if ( !outResult )
|
||||
return;
|
||||
*outResult = nil;
|
||||
mCacheVersion++;
|
||||
}
|
||||
|
||||
- (void)updateItemProperties:(id)item enumerateChildren:(BOOL)doChildren
|
||||
{
|
||||
BOOL isExpandable = NO;
|
||||
NSMutableArray* itemChildren = doChildren ? [[[NSMutableArray alloc] initWithCapacity:10] autorelease] : nil;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> itemResource = dont_AddRef([item resource]);
|
||||
|
||||
PRBool isSeq = PR_FALSE;
|
||||
mContainerUtils->IsSeq(mDataSource, itemResource, &isSeq);
|
||||
if (isSeq)
|
||||
isExpandable = YES;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childProperty;
|
||||
mRDFService->GetResource("http://home.netscape.com/NC-rdf#child", getter_AddRefs(childProperty));
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> childNodes;
|
||||
mDataSource->GetTargets(itemResource, childProperty, PR_TRUE, getter_AddRefs(childNodes));
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while (NS_SUCCEEDED(childNodes->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
nsCOMPtr<nsISupports> supp;
|
||||
childNodes->GetNext(getter_AddRefs(supp));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> childResource = do_QueryInterface(supp);
|
||||
if (childResource)
|
||||
{
|
||||
id childItem = [self getWrapperFor:childResource];
|
||||
if (childItem)
|
||||
{
|
||||
isExpandable = YES;
|
||||
if (!itemChildren) break; // know enough already
|
||||
[itemChildren addObject:childItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// itemChildren will be nil here if we don't care about children, but that's OK.
|
||||
// the setChildren call will clear the cached child list.
|
||||
[item setNumChildren:[itemChildren count] isExpandable:isExpandable cacheVersion:mCacheVersion];
|
||||
[item setChildren:itemChildren];
|
||||
}
|
||||
|
||||
- (NSString*)getPropertyString:(NSString*)inPropertyURI forItem:(RDFOutlineViewItem*)inItem
|
||||
{
|
||||
nsCOMPtr<nsIRDFResource> propertyResource;
|
||||
mRDFService->GetResource([inPropertyURI UTF8String], getter_AddRefs(propertyResource));
|
||||
|
||||
|
@ -378,38 +449,20 @@
|
|||
#if DEBUG
|
||||
NSLog(@"ValueNode is null in RDF objectValueForTableColumn");
|
||||
#endif
|
||||
return;
|
||||
return @"";
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> valueLiteral(do_QueryInterface(valueNode));
|
||||
if (!valueLiteral)
|
||||
return;
|
||||
return @"";
|
||||
|
||||
valueLiteral->GetValue(outResult);
|
||||
const PRUnichar* value = NULL;
|
||||
valueLiteral->GetValueConst(&value);
|
||||
if (value)
|
||||
return [NSString stringWithCharacters:value length:nsCRT::strlen(value)];
|
||||
|
||||
return @"";
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation RDFOutlineViewItem
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
NS_IF_RELEASE(mResource);
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (nsIRDFResource*) resource
|
||||
{
|
||||
NS_IF_ADDREF(mResource);
|
||||
return mResource;
|
||||
}
|
||||
|
||||
- (void) setResource: (nsIRDFResource*) aResource
|
||||
{
|
||||
nsIRDFResource* oldResource = mResource;
|
||||
NS_IF_ADDREF(mResource = aResource);
|
||||
NS_IF_RELEASE(oldResource);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -49,17 +49,23 @@ class HistoryDataSourceObserver;
|
|||
{
|
||||
HistoryDataSourceObserver* mObserver; // STRONG ref, should be nsCOMPtr but can't
|
||||
IBOutlet BrowserWindowController* mBrowserWindowController;
|
||||
BOOL mUpdatesEnabled;
|
||||
BOOL mNeedsRefresh;
|
||||
}
|
||||
|
||||
// overridden to create a attributed string with icon
|
||||
-(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem;
|
||||
- (id)createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem;
|
||||
|
||||
- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)inItem;
|
||||
|
||||
-(void) enableObserver;
|
||||
-(void) disableObserver;
|
||||
- (void)enableObserver;
|
||||
- (void)disableObserver;
|
||||
|
||||
-(IBAction)openHistoryItem: (id)aSender;
|
||||
-(IBAction)deleteHistoryItems: (id)aSender;
|
||||
- (void)setNeedsRefresh:(BOOL)needsRefresh;
|
||||
- (BOOL)needsRefresh;
|
||||
- (void)refresh;
|
||||
|
||||
- (IBAction)openHistoryItem: (id)aSender;
|
||||
- (IBAction)deleteHistoryItems: (id)aSender;
|
||||
|
||||
@end
|
||||
|
|
|
@ -63,33 +63,29 @@
|
|||
class HistoryDataSourceObserver : public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
HistoryDataSourceObserver(NSOutlineView* outlineView) :
|
||||
mOutlineView(outlineView), mEnabled(false)
|
||||
HistoryDataSourceObserver(HistoryDataSource* dataSource)
|
||||
: mHistoryDataSource(dataSource)
|
||||
{
|
||||
NS_INIT_ISUPPORTS();
|
||||
}
|
||||
virtual ~HistoryDataSourceObserver() { } ;
|
||||
virtual ~HistoryDataSourceObserver() { }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHODIMP OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) ;
|
||||
NS_IMETHODIMP OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*) { return NS_OK; }
|
||||
NS_IMETHOD OnAssert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*);
|
||||
NS_IMETHOD OnUnassert(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*);
|
||||
|
||||
NS_IMETHODIMP OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*)
|
||||
NS_IMETHOD OnMove(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*)
|
||||
{ return NS_OK; }
|
||||
|
||||
NS_IMETHODIMP OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*);
|
||||
NS_IMETHOD OnChange(nsIRDFDataSource*, nsIRDFResource*, nsIRDFResource*, nsIRDFNode*, nsIRDFNode*);
|
||||
|
||||
NS_IMETHODIMP BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; }
|
||||
NS_IMETHODIMP EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; }
|
||||
|
||||
void Enable() { mEnabled = true; }
|
||||
void Disable() { mEnabled = false; }
|
||||
NS_IMETHOD BeginUpdateBatch(nsIRDFDataSource*) { return NS_OK; }
|
||||
NS_IMETHOD EndUpdateBatch(nsIRDFDataSource*) { return NS_OK; }
|
||||
|
||||
private:
|
||||
|
||||
NSOutlineView* mOutlineView;
|
||||
bool mEnabled;
|
||||
HistoryDataSource* mHistoryDataSource;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(HistoryDataSourceObserver, nsIRDFObserver)
|
||||
|
@ -105,15 +101,30 @@ NS_IMETHODIMP
|
|||
HistoryDataSourceObserver::OnAssert(nsIRDFDataSource*, nsIRDFResource*,
|
||||
nsIRDFResource* aProperty, nsIRDFNode*)
|
||||
{
|
||||
if(mEnabled) {
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mOutlineView reloadData];
|
||||
}
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mHistoryDataSource setNeedsRefresh:YES];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnUnassert
|
||||
//
|
||||
// This gets called on redirects, when nsGlobalHistory::RemovePage is called.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
HistoryDataSourceObserver::OnUnassert(nsIRDFDataSource*, nsIRDFResource*,
|
||||
nsIRDFResource* aProperty, nsIRDFNode*)
|
||||
{
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mHistoryDataSource setNeedsRefresh:YES];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// OnChange
|
||||
|
@ -125,12 +136,12 @@ NS_IMETHODIMP
|
|||
HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
||||
nsIRDFResource* aProperty, nsIRDFNode*, nsIRDFNode*)
|
||||
{
|
||||
if(mEnabled) {
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mOutlineView reloadData];
|
||||
}
|
||||
const char* p;
|
||||
aProperty->GetValueConst(&p);
|
||||
|
||||
if (strcmp("http://home.netscape.com/NC-rdf#Date", p) == 0)
|
||||
[mHistoryDataSource setNeedsRefresh:YES];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -138,7 +149,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
|
||||
@interface HistoryDataSource(Private)
|
||||
|
||||
- (void)cleanup;
|
||||
- (void)cleanupHistory;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -146,12 +157,12 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
[self cleanup];
|
||||
[self cleanupHistory];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
// "non-virtual" cleanup method -- safe to call from dealloc.
|
||||
- (void)cleanup
|
||||
- (void)cleanupHistory
|
||||
{
|
||||
if (mDataSource && mObserver)
|
||||
{
|
||||
|
@ -163,7 +174,7 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
// "virtual" method; called from superclass
|
||||
- (void)cleanupDataSource
|
||||
{
|
||||
[self cleanup];
|
||||
[self cleanupHistory];
|
||||
[super cleanupDataSource];
|
||||
}
|
||||
|
||||
|
@ -181,7 +192,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
|
||||
NS_ASSERTION(mRDFService, "Uh oh, RDF service not loaded in parent class");
|
||||
|
||||
if ( !mDataSource ) {
|
||||
if ( !mDataSource )
|
||||
{
|
||||
// Get the Global History DataSource
|
||||
mRDFService->GetDataSource("rdf:history", &mDataSource);
|
||||
// Get the Date Folder Root
|
||||
|
@ -191,14 +203,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
[mOutlineView setDoubleAction: @selector(openHistoryItem:)];
|
||||
[mOutlineView setDeleteAction: @selector(deleteHistoryItems:)];
|
||||
|
||||
mObserver = new HistoryDataSourceObserver(mOutlineView);
|
||||
mObserver = new HistoryDataSourceObserver(self);
|
||||
if ( mObserver ) {
|
||||
NS_ADDREF(mObserver);
|
||||
mDataSource->AddObserver(mObserver);
|
||||
}
|
||||
[mOutlineView reloadData];
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
// everything is loaded, but we have to refresh our tree otherwise
|
||||
// changes that took place while the drawer was closed won't be noticed
|
||||
[mOutlineView reloadData];
|
||||
|
@ -207,18 +220,41 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
NS_ASSERTION(mDataSource, "Uh oh, History RDF Data source not created");
|
||||
}
|
||||
|
||||
- (void) enableObserver
|
||||
- (void)enableObserver
|
||||
{
|
||||
if ( mObserver )
|
||||
mObserver->Enable();
|
||||
mUpdatesEnabled = YES;
|
||||
}
|
||||
|
||||
-(void) disableObserver
|
||||
-(void)disableObserver
|
||||
{
|
||||
if ( mObserver )
|
||||
mObserver->Disable();
|
||||
mUpdatesEnabled = NO;
|
||||
}
|
||||
|
||||
- (void)setNeedsRefresh:(BOOL)needsRefresh
|
||||
{
|
||||
mNeedsRefresh = needsRefresh;
|
||||
}
|
||||
|
||||
- (BOOL)needsRefresh
|
||||
{
|
||||
return mNeedsRefresh;
|
||||
}
|
||||
|
||||
- (void)refresh
|
||||
{
|
||||
if (mNeedsRefresh)
|
||||
{
|
||||
[self invalidateCachedItems];
|
||||
if (mUpdatesEnabled)
|
||||
{
|
||||
// this can be very slow! See bug 180109.
|
||||
//NSLog(@"history reload started");
|
||||
[self reloadDataForItem:nil reloadChildren:NO];
|
||||
//NSLog(@"history reload done");
|
||||
}
|
||||
mNeedsRefresh = NO;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// createCellContents:withColumn:byItem
|
||||
|
@ -226,31 +262,29 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
// override to create an NSAttributedString instead of just the string with the
|
||||
// given text. We add an icon and adjust the positioning of the text w/in the cell
|
||||
//
|
||||
-(id) createCellContents:(const nsAString&)inValue withColumn:(NSString*)inColumn byItem:(id) inItem
|
||||
-(id) createCellContents:(NSString*)inValue withColumn:(NSString*)inColumn byItem:(id) inItem
|
||||
{
|
||||
NSMutableAttributedString *cellValue = [[NSMutableAttributedString alloc] init];
|
||||
|
||||
//Set cell's textual contents
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString:inValue]];
|
||||
if ([inValue length] == 0)
|
||||
inValue = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem];
|
||||
|
||||
if ([inColumn isEqualToString: @"http://home.netscape.com/NC-rdf#Name"]) {
|
||||
NSMutableAttributedString *attachmentAttrString = nil;
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
NSCell *attachmentAttrStringCell;
|
||||
NSMutableAttributedString *cellValue = [[[NSMutableAttributedString alloc] initWithString:inValue] autorelease];
|
||||
|
||||
if ([inColumn isEqualToString:@"http://home.netscape.com/NC-rdf#Name"])
|
||||
{
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
attachmentAttrString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] retain];
|
||||
// Create an attributed string to hold the empty attachment, then release the components.
|
||||
NSMutableAttributedString *attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment];
|
||||
[textAttachment release];
|
||||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:
|
||||
NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:
|
||||
NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
|
||||
if ([self outlineView:mOutlineView isItemExpandable:inItem]) {
|
||||
if ([self outlineView:mOutlineView isItemExpandable:inItem])
|
||||
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]];
|
||||
}
|
||||
else
|
||||
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]];
|
||||
|
||||
|
@ -298,11 +332,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
id item = [toDrag objectAtIndex: 0];
|
||||
|
||||
// if we have just one item, we add some more flavours
|
||||
nsXPIDLString urlLiteral, nameLiteral;
|
||||
[self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)];
|
||||
[self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item result:getter_Copies(nameLiteral)];
|
||||
NSString* url = [NSString stringWith_nsAString: urlLiteral];
|
||||
NSString* title = [NSString stringWith_nsAString: nameLiteral];
|
||||
NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item];
|
||||
NSString* title = [self getPropertyString:@"http://home.netscape.com/NC-rdf#Name" forItem:item];
|
||||
NSString *cleanedTitle = [title stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "];
|
||||
|
||||
[pboard declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:self];
|
||||
|
@ -340,11 +371,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
return;
|
||||
}
|
||||
|
||||
nsXPIDLString urlLiteral;
|
||||
[self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)];
|
||||
|
||||
// get uri
|
||||
NSString* url = [NSString stringWith_nsAString: urlLiteral];
|
||||
NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item];
|
||||
[[mBrowserWindowController getBrowserWrapper] loadURI: url referrer: nil flags: NSLoadFlagsNone activate:YES];
|
||||
}
|
||||
|
||||
|
@ -376,14 +404,15 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
index = [currIndex intValue];
|
||||
RDFOutlineViewItem* item = [mOutlineView itemAtRow: index];
|
||||
if (![mOutlineView isExpandable: item]) {
|
||||
nsXPIDLString urlLiteral;
|
||||
[self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item result:getter_Copies(urlLiteral)];
|
||||
history->RemovePage(NS_ConvertUCS2toUTF8(urlLiteral).get());
|
||||
NSString* urlString = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:item];
|
||||
history->RemovePage([urlString UTF8String]);
|
||||
}
|
||||
}
|
||||
history->EndBatchUpdate();
|
||||
if ( clearSelectionWhenDone )
|
||||
[mOutlineView deselectAll:self];
|
||||
|
||||
[self invalidateCachedItems];
|
||||
[mOutlineView reloadData]; // necessary or the outline is really horked
|
||||
}
|
||||
}
|
||||
|
@ -402,9 +431,8 @@ HistoryDataSourceObserver::OnChange(nsIRDFDataSource*, nsIRDFResource*,
|
|||
NSString* pageTitle = [super outlineView:outlineView tooltipStringForItem:inItem];
|
||||
|
||||
// append url
|
||||
nsXPIDLString literalValue;
|
||||
[self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem result:getter_Copies(literalValue)];
|
||||
return [NSString stringWithFormat:@"%@\n%@", pageTitle, [NSString stringWith_nsAString:literalValue]];
|
||||
NSString* url = [self getPropertyString:@"http://home.netscape.com/NC-rdf#URL" forItem:inItem];
|
||||
return [NSString stringWithFormat:@"%@\n%@", pageTitle, [url stringByTruncatingTo:80 at:kTruncateAtEnd]];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
|
|
@ -52,3 +52,13 @@ const int kDividerTag = 4000;
|
|||
|
||||
// the tag of the separator after which to insert bookmark items
|
||||
const int kBookmarksDividerTag = -1;
|
||||
|
||||
// Save file dialog
|
||||
const int kSaveFormatPopupTag = 1000;
|
||||
|
||||
enum
|
||||
{
|
||||
eSaveFormatHTMLComplete = 0,
|
||||
eSaveFormatHTMLSource,
|
||||
eSaveFormatPlainText
|
||||
};
|
||||
|
|
|
@ -45,6 +45,9 @@ class nsIPref;
|
|||
NSUserDefaults* mDefaults;
|
||||
ICInstance mInternetConfig;
|
||||
nsIPref* mPrefs;
|
||||
|
||||
// proxies notification stuff
|
||||
CFRunLoopSourceRef mRunLoopSource;
|
||||
}
|
||||
|
||||
+ (PreferenceManager *)sharedInstance;
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
|
||||
#import "PreferenceManager.h"
|
||||
#import "UserDefaults.h"
|
||||
#import "CHBrowserService.h"
|
||||
|
@ -60,11 +61,23 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
|
|||
|
||||
@interface PreferenceManager(PreferenceManagerPrivate)
|
||||
|
||||
+ (PreferenceManager *) sharedInstanceDontCreate;
|
||||
|
||||
- (void)registerNotificationListener;
|
||||
|
||||
- (void)termEmbedding: (NSNotification*)aNotification;
|
||||
- (void)xpcomTerminate: (NSNotification*)aNotification;
|
||||
|
||||
- (void)configureProxies;
|
||||
- (BOOL)updateOneProxy:(NSDictionary*)configDict
|
||||
protocol:(NSString*)protocol
|
||||
proxyEnableKey:(NSString*)enableKey
|
||||
proxyURLKey:(NSString*)urlKey
|
||||
proxyPortKey:(NSString*)portKey;
|
||||
|
||||
- (void)registerForProxyChanges;
|
||||
- (BOOL)readSystemProxySettings;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -76,7 +89,7 @@ static PreferenceManager* gSharedInstance = nil;
|
|||
static BOOL gMadePrefManager;
|
||||
#endif
|
||||
|
||||
+ (PreferenceManager *) sharedInstance
|
||||
+ (PreferenceManager *)sharedInstance
|
||||
{
|
||||
if (!gSharedInstance)
|
||||
{
|
||||
|
@ -88,13 +101,20 @@ static BOOL gMadePrefManager;
|
|||
gSharedInstance = [[PreferenceManager alloc] init];
|
||||
}
|
||||
|
||||
return gSharedInstance;
|
||||
return gSharedInstance;
|
||||
}
|
||||
|
||||
+ (PreferenceManager *)sharedInstanceDontCreate
|
||||
{
|
||||
return gSharedInstance;
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
mRunLoopSource = NULL;
|
||||
|
||||
[self registerNotificationListener];
|
||||
|
||||
if ([self initInternetConfig] == NO) {
|
||||
|
@ -115,6 +135,8 @@ static BOOL gMadePrefManager;
|
|||
- (void) dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
if (self == gSharedInstance)
|
||||
gSharedInstance = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
@ -123,6 +145,13 @@ static BOOL gMadePrefManager;
|
|||
::ICStop(mInternetConfig);
|
||||
mInternetConfig = nil;
|
||||
NS_IF_RELEASE(mPrefs);
|
||||
// remove our runloop observer
|
||||
if (mRunLoopSource)
|
||||
{
|
||||
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), mRunLoopSource, kCFRunLoopCommonModes);
|
||||
CFRelease(mRunLoopSource);
|
||||
mRunLoopSource = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)xpcomTerminate: (NSNotification*)aNotification
|
||||
|
@ -145,14 +174,14 @@ static BOOL gMadePrefManager;
|
|||
object: nil];
|
||||
}
|
||||
|
||||
- (void) savePrefsFile
|
||||
- (void)savePrefsFile
|
||||
{
|
||||
nsCOMPtr<nsIPrefService> prefsService = do_GetService(NS_PREF_CONTRACTID);
|
||||
if (prefsService)
|
||||
prefsService->SavePrefFile(nsnull);
|
||||
}
|
||||
|
||||
- (BOOL) initInternetConfig
|
||||
- (BOOL)initInternetConfig
|
||||
{
|
||||
OSStatus error;
|
||||
error = ::ICStart(&mInternetConfig, 'CHIM');
|
||||
|
@ -164,7 +193,7 @@ static BOOL gMadePrefManager;
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL) initMozillaPrefs
|
||||
- (BOOL)initMozillaPrefs
|
||||
{
|
||||
|
||||
#ifdef _BUILD_STATIC_BIN
|
||||
|
@ -246,15 +275,8 @@ static BOOL gMadePrefManager;
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (void) syncMozillaPrefs
|
||||
- (void)syncMozillaPrefs
|
||||
{
|
||||
CFArrayRef cfArray;
|
||||
CFDictionaryRef cfDictionary;
|
||||
CFNumberRef cfNumber;
|
||||
CFStringRef cfString;
|
||||
char strbuf[1024];
|
||||
int numbuf;
|
||||
|
||||
if (!mPrefs) {
|
||||
NSLog(@"Mozilla prefs not set up successfully");
|
||||
return;
|
||||
|
@ -268,19 +290,101 @@ static BOOL gMadePrefManager;
|
|||
// fix up the cookie prefs. If 'p3p' or 'accept foreign cookies' are on, remap them to
|
||||
// something that chimera can deal with.
|
||||
PRInt32 acceptCookies = 0;
|
||||
static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior";
|
||||
static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior";
|
||||
mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
|
||||
if ( acceptCookies == 1 ) { // accept foreign cookies, assume off
|
||||
if ( acceptCookies == 1 ) { // accept foreign cookies, assume off
|
||||
acceptCookies = 2;
|
||||
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
|
||||
}
|
||||
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
|
||||
}
|
||||
else if ( acceptCookies == 3 ) { // p3p, assume all cookies on
|
||||
acceptCookies = 0;
|
||||
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
|
||||
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
|
||||
}
|
||||
|
||||
|
||||
[self configureProxies];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)configureProxies
|
||||
{
|
||||
[self readSystemProxySettings];
|
||||
[self registerForProxyChanges];
|
||||
}
|
||||
|
||||
static void SCProxiesChangedCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void * /* info */)
|
||||
{
|
||||
PreferenceManager* prefsManager = [PreferenceManager sharedInstanceDontCreate];
|
||||
[prefsManager readSystemProxySettings];
|
||||
#if DEBUG
|
||||
NSLog(@"Updating proxies");
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)registerForProxyChanges
|
||||
{
|
||||
if (mRunLoopSource) // don't register twice
|
||||
return;
|
||||
|
||||
SCDynamicStoreContext context = {0, NULL, NULL, NULL, NULL};
|
||||
|
||||
SCDynamicStoreRef dynamicStoreRef = SCDynamicStoreCreate(NULL, CFSTR("ChimeraProxiesNotification"), SCProxiesChangedCallback, &context);
|
||||
if (dynamicStoreRef)
|
||||
{
|
||||
CFStringRef proxyIdentifier = SCDynamicStoreKeyCreateProxies(NULL);
|
||||
CFArrayRef keyList = CFArrayCreate(NULL, (const void **)&proxyIdentifier, 1, &kCFTypeArrayCallBacks);
|
||||
|
||||
Boolean set = SCDynamicStoreSetNotificationKeys(dynamicStoreRef, keyList, NULL);
|
||||
if (set)
|
||||
{
|
||||
mRunLoopSource = SCDynamicStoreCreateRunLoopSource(NULL, dynamicStoreRef, 0);
|
||||
if (mRunLoopSource)
|
||||
{
|
||||
CFRunLoopAddSource(CFRunLoopGetCurrent(), mRunLoopSource, kCFRunLoopCommonModes);
|
||||
// we keep the ref to the source, so that we can remove it when the prefs manager is cleaned up.
|
||||
}
|
||||
}
|
||||
|
||||
CFRelease(proxyIdentifier);
|
||||
CFRelease(keyList);
|
||||
CFRelease(dynamicStoreRef);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)updateOneProxy:(NSDictionary*)configDict
|
||||
protocol:(NSString*)protocol
|
||||
proxyEnableKey:(NSString*)enableKey
|
||||
proxyURLKey:(NSString*)urlKey
|
||||
proxyPortKey:(NSString*)portKey
|
||||
{
|
||||
BOOL gotProxy = NO;
|
||||
|
||||
BOOL enabled = (BOOL)[[configDict objectForKey:enableKey] intValue];
|
||||
if (enabled)
|
||||
{
|
||||
NSString* protocolProxy = [configDict objectForKey:urlKey];
|
||||
int proxyPort = [[configDict objectForKey:portKey] intValue];
|
||||
if ([protocolProxy length] > 0 && proxyPort != 0)
|
||||
{
|
||||
[self setPref:[[NSString stringWithFormat:@"network.proxy.%@", protocol] cString] toString:protocolProxy];
|
||||
[self setPref:[[NSString stringWithFormat:@"network.proxy.%@_port", protocol] cString] toInt:proxyPort];
|
||||
gotProxy = YES;
|
||||
}
|
||||
}
|
||||
|
||||
return gotProxy;
|
||||
}
|
||||
|
||||
- (BOOL)readSystemProxySettings
|
||||
{
|
||||
BOOL usingProxies = NO;
|
||||
|
||||
PRInt32 proxyType, newProxyType;
|
||||
mPrefs->GetIntPref("network.proxy.type", &proxyType);
|
||||
newProxyType = proxyType;
|
||||
if (proxyType == 0 || proxyType == 1)
|
||||
{
|
||||
// get proxies from SystemConfiguration
|
||||
mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
|
||||
mPrefs->ClearUserPref("network.proxy.http");
|
||||
mPrefs->ClearUserPref("network.proxy.http_port");
|
||||
mPrefs->ClearUserPref("network.proxy.ssl");
|
||||
|
@ -293,94 +397,66 @@ static BOOL gMadePrefManager;
|
|||
mPrefs->ClearUserPref("network.proxy.socks_port");
|
||||
mPrefs->ClearUserPref("network.proxy.no_proxies_on");
|
||||
|
||||
if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) {
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) {
|
||||
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
|
||||
mPrefs->SetCharPref("network.proxy.http", strbuf);
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
|
||||
mPrefs->SetIntPref("network.proxy.http_port", numbuf);
|
||||
}
|
||||
mPrefs->SetIntPref("network.proxy.type", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
NSDictionary* proxyConfigDict = (NSDictionary*)SCDynamicStoreCopyProxies(NULL);
|
||||
if (proxyConfigDict)
|
||||
{
|
||||
BOOL gotAProxy = NO;
|
||||
|
||||
gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"http"
|
||||
proxyEnableKey:(NSString*)kSCPropNetProxiesHTTPEnable
|
||||
proxyURLKey:(NSString*)kSCPropNetProxiesHTTPProxy
|
||||
proxyPortKey:(NSString*)kSCPropNetProxiesHTTPPort];
|
||||
|
||||
gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"ssl"
|
||||
proxyEnableKey:(NSString*)kSCPropNetProxiesHTTPSEnable
|
||||
proxyURLKey:(NSString*)kSCPropNetProxiesHTTPSProxy
|
||||
proxyPortKey:(NSString*)kSCPropNetProxiesHTTPSPort];
|
||||
|
||||
gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"ftp"
|
||||
proxyEnableKey:(NSString*)kSCPropNetProxiesFTPEnable
|
||||
proxyURLKey:(NSString*)kSCPropNetProxiesFTPProxy
|
||||
proxyPortKey:(NSString*)kSCPropNetProxiesFTPPort];
|
||||
|
||||
gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"gopher"
|
||||
proxyEnableKey:(NSString*)kSCPropNetProxiesGopherEnable
|
||||
proxyURLKey:(NSString*)kSCPropNetProxiesGopherProxy
|
||||
proxyPortKey:(NSString*)kSCPropNetProxiesGopherPort];
|
||||
|
||||
gotAProxy |= [self updateOneProxy:proxyConfigDict protocol:@"socks"
|
||||
proxyEnableKey:(NSString*)kSCPropNetProxiesSOCKSEnable
|
||||
proxyURLKey:(NSString*)kSCPropNetProxiesSOCKSProxy
|
||||
proxyPortKey:(NSString*)kSCPropNetProxiesSOCKSPort];
|
||||
|
||||
if (gotAProxy)
|
||||
{
|
||||
newProxyType = 1;
|
||||
|
||||
NSArray* exceptions = [proxyConfigDict objectForKey:(NSString*)kSCPropNetProxiesExceptionsList];
|
||||
if (exceptions)
|
||||
{
|
||||
NSString* sitesList = [exceptions componentsJoinedByString:@", "];
|
||||
if ([sitesList length] > 0)
|
||||
[self setPref:"network.proxy.no_proxies_on" toString:sitesList];
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSEnable, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) {
|
||||
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
|
||||
mPrefs->SetCharPref("network.proxy.ssl", strbuf);
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
|
||||
mPrefs->SetIntPref("network.proxy.ssl_port", numbuf);
|
||||
}
|
||||
mPrefs->SetIntPref("network.proxy.type", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPEnable, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) {
|
||||
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
|
||||
mPrefs->SetCharPref("network.proxy.ftp", strbuf);
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
|
||||
mPrefs->SetIntPref("network.proxy.ftp_port", numbuf);
|
||||
}
|
||||
mPrefs->SetIntPref("network.proxy.type", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherEnable, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) {
|
||||
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
|
||||
mPrefs->SetCharPref("network.proxy.gopher", strbuf);
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
|
||||
mPrefs->SetIntPref("network.proxy.gopher_port", numbuf);
|
||||
}
|
||||
mPrefs->SetIntPref("network.proxy.type", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSEnable, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) {
|
||||
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
|
||||
mPrefs->SetCharPref("network.proxy.socks", strbuf);
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) {
|
||||
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
|
||||
mPrefs->SetIntPref("network.proxy.socks_port", numbuf);
|
||||
}
|
||||
mPrefs->SetIntPref("network.proxy.type", 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesExceptionsList, (const void **)&cfArray) == TRUE) {
|
||||
cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", "));
|
||||
if (CFStringGetLength (cfString) > 0) {
|
||||
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
|
||||
mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
CFRelease (cfDictionary);
|
||||
usingProxies = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
newProxyType = 0;
|
||||
}
|
||||
|
||||
[proxyConfigDict release];
|
||||
}
|
||||
|
||||
if (newProxyType != proxyType)
|
||||
mPrefs->SetIntPref("network.proxy.type", 1);
|
||||
}
|
||||
|
||||
return usingProxies;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
|
||||
{
|
||||
NSString *prefValue = @"";
|
||||
|
@ -406,16 +482,16 @@ static BOOL gMadePrefManager;
|
|||
{
|
||||
// colors are stored in HTML-like #FFFFFF strings
|
||||
NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess];
|
||||
NSColor* returnColor = [NSColor blackColor];
|
||||
NSColor* returnColor = [NSColor blackColor];
|
||||
|
||||
if ([colorString hasPrefix:@"#"] && [colorString length] == 7)
|
||||
{
|
||||
unsigned int redInt, greenInt, blueInt;
|
||||
sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt);
|
||||
|
||||
float redFloat = ((float)redInt / 255.0);
|
||||
float greenFloat = ((float)greenInt / 255.0);
|
||||
float blueFloat = ((float)blueInt / 255.0);
|
||||
float redFloat = ((float)redInt / 255.0);
|
||||
float greenFloat = ((float)greenInt / 255.0);
|
||||
float blueFloat = ((float)blueInt / 255.0);
|
||||
|
||||
returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f];
|
||||
}
|
||||
|
@ -548,7 +624,7 @@ static BOOL gMadePrefManager;
|
|||
mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
|
||||
}
|
||||
else {
|
||||
homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL];
|
||||
homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL];
|
||||
}
|
||||
|
||||
if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"])
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>646 106 458 263 0 0 1600 1002 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>214</key>
|
||||
<string>70 395 152 96 0 0 1152 746 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6D52</string>
|
||||
</dict>
|
||||
</plist>
|
Двоичные данные
chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib
сгенерированный
Двоичные данные
chimera/PreferencePanes/Appearance/English.lproj/Appearance.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>140 56 522 320 0 0 1280 1002 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
<key>IBGroupedObjects</key>
|
||||
<dict>
|
||||
<key>5</key>
|
||||
<array>
|
||||
<string>12</string>
|
||||
<string>24</string>
|
||||
<string>56</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>8</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>5</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
</dict>
|
||||
</plist>
|
Двоичные данные
chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib
сгенерированный
Двоичные данные
chimera/PreferencePanes/Navigation/English.lproj/Navigation.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
|
@ -1,177 +0,0 @@
|
|||
{
|
||||
IBClasses = (
|
||||
{CLASS = AutoCompleteDataSource; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
ACTIONS = {onBlur = id; onResize = id; };
|
||||
CLASS = AutoCompleteTextField;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mProxyIcon = PageProxyIcon; };
|
||||
SUPERCLASS = NSTextField;
|
||||
},
|
||||
{CLASS = BookmarkItem; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
ACTIONS = {
|
||||
addBookmark = id;
|
||||
addFolder = id;
|
||||
deleteBookmarks = id;
|
||||
openBookmarkInNewTab = id;
|
||||
openBookmarkInNewWindow = id;
|
||||
showBookmarkInfo = id;
|
||||
};
|
||||
CLASS = BookmarksDataSource;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mBrowserWindowController = id;
|
||||
mDeleteBookmarkButton = id;
|
||||
mEditBookmarkButton = id;
|
||||
mOutlineView = id;
|
||||
};
|
||||
SUPERCLASS = NSObject;
|
||||
},
|
||||
{
|
||||
CLASS = BookmarksOutlineView;
|
||||
LANGUAGE = ObjC;
|
||||
SUPERCLASS = ExtendedOutlineView;
|
||||
},
|
||||
{
|
||||
ACTIONS = {addFolder = id; };
|
||||
CLASS = BookmarksToolbar;
|
||||
LANGUAGE = ObjC;
|
||||
SUPERCLASS = NSView;
|
||||
},
|
||||
{CLASS = BrowserContainerView; LANGUAGE = ObjC; SUPERCLASS = NSView; },
|
||||
{
|
||||
CLASS = BrowserContentView;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mBookmarksToolbar = BookmarksToolbar;
|
||||
mBrowserContainerView = NSView;
|
||||
mStatusBar = NSView;
|
||||
};
|
||||
SUPERCLASS = NSView;
|
||||
},
|
||||
{CLASS = BrowserTabView; LANGUAGE = ObjC; SUPERCLASS = NSTabView; },
|
||||
{
|
||||
CLASS = BrowserWindow;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mAutoCompleteTextField = id; };
|
||||
SUPERCLASS = NSWindow;
|
||||
},
|
||||
{
|
||||
ACTIONS = {
|
||||
back = id;
|
||||
biggerTextSize = id;
|
||||
bookmarkLink = id;
|
||||
bookmarkPage = id;
|
||||
cancelAddBookmarkSheet = id;
|
||||
cancelLocationSheet = id;
|
||||
closeCurrentTab = id;
|
||||
closeOtherTabs = id;
|
||||
closeSendersTab = id;
|
||||
copyImageLocation = id;
|
||||
copyLinkLocation = id;
|
||||
endAddBookmarkSheet = id;
|
||||
endLocationSheet = id;
|
||||
forward = id;
|
||||
frameToNewTab = id;
|
||||
frameToNewWindow = id;
|
||||
frameToThisWindow = id;
|
||||
getInfo = id;
|
||||
goToLocationFromToolbarURLField = id;
|
||||
home = id;
|
||||
manageBookmarks = id;
|
||||
moveTabToNewWindow = id;
|
||||
newTab = id;
|
||||
nextTab = id;
|
||||
openLinkInNewTab = id;
|
||||
openLinkInNewWindow = id;
|
||||
pageSetup = id;
|
||||
performSearch = id;
|
||||
previousTab = id;
|
||||
printDocument = id;
|
||||
reload = id;
|
||||
reloadSendersTab = id;
|
||||
saveFrameAs = id;
|
||||
saveImageAs = id;
|
||||
saveLinkAs = id;
|
||||
savePageAs = id;
|
||||
sendURL = id;
|
||||
smallerTextSize = id;
|
||||
stop = id;
|
||||
toggleSidebar = id;
|
||||
viewOnlyThisImage = id;
|
||||
viewPageSource = id;
|
||||
viewSource = id;
|
||||
};
|
||||
CLASS = BrowserWindowController;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mAddBookmarkCheckbox = NSButton;
|
||||
mAddBookmarkFolderField = NSPopUpButton;
|
||||
mAddBookmarkSheetWindow = NSWindow;
|
||||
mAddBookmarkTitleField = NSTextField;
|
||||
mBackItem = NSMenuItem;
|
||||
mContentView = BrowserContentView;
|
||||
mCopyItem = NSMenuItem;
|
||||
mForwardItem = NSMenuItem;
|
||||
mHistoryDataSource = HistoryDataSource;
|
||||
mImageLinkMenu = NSMenu;
|
||||
mImageMenu = NSMenu;
|
||||
mInputMenu = NSMenu;
|
||||
mLinkMenu = NSMenu;
|
||||
mLocationSheetURLField = NSTextField;
|
||||
mLocationSheetWindow = NSWindow;
|
||||
mLocationToolbarView = NSView;
|
||||
mLock = NSImageView;
|
||||
mPageMenu = NSMenu;
|
||||
mPersonalToolbar = BookmarksToolbar;
|
||||
mProgress = NSProgressIndicator;
|
||||
mProxyIcon = PageProxyIcon;
|
||||
mSidebarBookmarksDataSource = BookmarksDataSource;
|
||||
mSidebarDrawer = NSDrawer;
|
||||
mSidebarSourceTabView = NSTabView;
|
||||
mSidebarTabView = NSTabView;
|
||||
mStatus = NSTextField;
|
||||
mStatusBar = NSView;
|
||||
mTabBrowser = BrowserTabView;
|
||||
mTabMenu = NSMenu;
|
||||
mURLBar = NSTextField;
|
||||
};
|
||||
SUPERCLASS = NSWindowController;
|
||||
},
|
||||
{
|
||||
ACTIONS = {load = id; };
|
||||
CLASS = BrowserWrapper;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mLockIcon = id;
|
||||
mWindowController = id;
|
||||
progress = id;
|
||||
progressSuper = id;
|
||||
status = id;
|
||||
urlbar = id;
|
||||
};
|
||||
SUPERCLASS = NSView;
|
||||
},
|
||||
{CLASS = ExtendedOutlineView; LANGUAGE = ObjC; SUPERCLASS = NSOutlineView; },
|
||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
CLASS = HistoryDataSource;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mBrowserWindowController = id; };
|
||||
SUPERCLASS = RDFOutlineViewDataSource;
|
||||
},
|
||||
{CLASS = LocationBar; LANGUAGE = ObjC; SUPERCLASS = NSView; },
|
||||
{CLASS = MainController; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{CLASS = PageProxyIcon; LANGUAGE = ObjC; SUPERCLASS = NSImageView; },
|
||||
{
|
||||
CLASS = RDFOutlineViewDataSource;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {mOutlineView = id; };
|
||||
SUPERCLASS = NSObject;
|
||||
},
|
||||
{CLASS = RDFOutlineViewItem; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{CLASS = ThrobberHandler; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
|
||||
);
|
||||
IBVersion = 1;
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>66 21 653 383 0 0 1152 848 </string>
|
||||
<string>65 36 653 383 0 0 1152 848 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>124</key>
|
||||
|
@ -15,17 +15,17 @@
|
|||
<key>297</key>
|
||||
<string>107 466 213 294 0 0 1600 1002 </string>
|
||||
<key>314</key>
|
||||
<string>73 542 213 132 0 0 1600 1002 </string>
|
||||
<string>72 544 213 150 0 0 1600 1002 </string>
|
||||
<key>336</key>
|
||||
<string>486 756 213 180 0 0 1600 1002 </string>
|
||||
<key>365</key>
|
||||
<string>31 719 93 162 0 0 1600 1002 </string>
|
||||
<key>463</key>
|
||||
<string>97 693 213 246 0 0 1600 1002 </string>
|
||||
<string>349 487 213 246 0 0 1600 1002 </string>
|
||||
<key>56</key>
|
||||
<string>450 634 343 68 0 0 1280 1002 </string>
|
||||
<key>654</key>
|
||||
<string>206 785 198 144 0 0 1600 1002 </string>
|
||||
<string>140 644 198 144 0 0 1152 848 </string>
|
||||
</dict>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
|
@ -42,6 +42,6 @@
|
|||
<key>IBLockedObjects</key>
|
||||
<array/>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичные данные
chimera/resources/localized/English.lproj/BrowserWindow.nib/objects.nib
сгенерированный
Двоичные данные
chimera/resources/localized/English.lproj/BrowserWindow.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
Двоичные данные
chimera/resources/localized/English.lproj/Localizable.strings
Двоичные данные
chimera/resources/localized/English.lproj/Localizable.strings
Двоичный файл не отображается.
|
@ -20,6 +20,7 @@
|
|||
doReload = id;
|
||||
doSearch = id;
|
||||
doStop = id;
|
||||
downloadsWindow = id;
|
||||
exportBookmarks = id;
|
||||
feedbackLink = id;
|
||||
findAgain = id;
|
||||
|
@ -61,7 +62,6 @@
|
|||
mCreateBookmarksFolderMenuItem = NSMenuItem;
|
||||
mCreateBookmarksSeparatorMenuItem = NSMenuItem;
|
||||
mDockMenu = NSMenu;
|
||||
mFilterList = NSPopUpButton;
|
||||
mFilterView = NSView;
|
||||
mGoMenu = NSMenu;
|
||||
mServersSubmenu = NSMenu;
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>237 33 482 372 0 0 1600 1002 </string>
|
||||
<string>105 33 482 372 0 0 1600 1002 </string>
|
||||
<key>IBEditorPositions</key>
|
||||
<dict>
|
||||
<key>266</key>
|
||||
<string>437 533 277 90 0 0 1152 848 </string>
|
||||
<string>644 623 277 90 0 0 1600 1002 </string>
|
||||
<key>29</key>
|
||||
<string>11 957 446 44 0 0 1600 1002 </string>
|
||||
<key>494</key>
|
||||
|
@ -31,7 +31,11 @@
|
|||
</dict>
|
||||
<key>IBLastGroupID</key>
|
||||
<string>2</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>29</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
<string>6G30</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичный файл не отображается.
|
@ -1,19 +0,0 @@
|
|||
{
|
||||
IBClasses = (
|
||||
{CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; },
|
||||
{
|
||||
CLASS = ProgressDlgController;
|
||||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
mElapsedTimeLabel = NSTextField;
|
||||
mFromField = NSTextField;
|
||||
mProgressBar = NSProgressIndicator;
|
||||
mStatusLabel = NSTextField;
|
||||
mTimeLeftLabel = NSTextField;
|
||||
mToField = NSTextField;
|
||||
};
|
||||
SUPERCLASS = NSWindowController;
|
||||
}
|
||||
);
|
||||
IBVersion = 1;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
|
||||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>94 26 404 250 0 0 1152 746 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>248.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>5S60</string>
|
||||
</dict>
|
||||
</plist>
|
Двоичные данные
chimera/resources/localized/English.lproj/ProgressDialog.nib/objects.nib
сгенерированный
Двоичные данные
chimera/resources/localized/English.lproj/ProgressDialog.nib/objects.nib
сгенерированный
Двоичный файл не отображается.
0
chimera/resources/localized/English.lproj/ProgressView.nib/classes.nib
сгенерированный
Normal file
0
chimera/resources/localized/English.lproj/ProgressView.nib/classes.nib
сгенерированный
Normal file
0
chimera/resources/localized/English.lproj/ProgressView.nib/objects.nib
сгенерированный
Normal file
0
chimera/resources/localized/English.lproj/ProgressView.nib/objects.nib
сгенерированный
Normal file
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IBDocumentLocation</key>
|
||||
<string>410 67 356 301 0 0 1152 848 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>286.0</string>
|
||||
<key>IBOpenObjects</key>
|
||||
<array>
|
||||
<integer>251</integer>
|
||||
</array>
|
||||
<key>IBSystem Version</key>
|
||||
<string>6F21</string>
|
||||
</dict>
|
||||
</plist>
|
Двоичный файл не отображается.
|
@ -37,10 +37,14 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "SecurityDialogs.h"
|
||||
#import "CocoaPromptService.h"
|
||||
#include "nsIGenericFactory.h"
|
||||
#import "KeychainService.h"
|
||||
#import "nsDownloadListener.h"
|
||||
#import "ProgressDlgController.h"
|
||||
|
||||
#include "nsIGenericFactory.h"
|
||||
|
||||
// {0ffd3880-7a1a-11d6-a384-975d1d5f86fc}
|
||||
#define NS_SECURITYDIALOGS_CID \
|
||||
|
@ -55,6 +59,27 @@
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(SecurityDialogs);
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(CocoaPromptService);
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(KeychainPrompt);
|
||||
//NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadListener);
|
||||
|
||||
static NS_IMETHODIMP
|
||||
nsDownloadListenerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
{
|
||||
*aResult = NULL;
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsDownloadListener* inst;
|
||||
NS_NEWXPCOM(inst, nsDownloadListener);
|
||||
if (!inst)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(inst);
|
||||
inst->SetDisplayFactory([ProgressDlgController sharedDownloadController]);
|
||||
nsresult rv = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
// used by MainController to register the components in which we want to override
|
||||
// with the Gecko embed layer.
|
||||
|
@ -83,6 +108,12 @@ static const nsModuleComponentInfo gAppComponents[] = {
|
|||
NS_KEYCHAINPROMPT_CID,
|
||||
"@mozilla.org/wallet/single-sign-on-prompt;1",
|
||||
KeychainPromptConstructor
|
||||
},
|
||||
{
|
||||
"Download",
|
||||
NS_DOWNLOAD_CID,
|
||||
NS_DOWNLOAD_CONTRACTID,
|
||||
nsDownloadListenerConstructor
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -52,9 +52,8 @@
|
|||
{
|
||||
IBOutlet NSApplication* mApplication;
|
||||
|
||||
// The following two items are used by the filter list when saving files.
|
||||
// The following item is added to NSSavePanels as an accessory view
|
||||
IBOutlet NSView* mFilterView;
|
||||
IBOutlet NSPopUpButton* mFilterList;
|
||||
|
||||
// IBOutlet NSMenuItem* mOfflineMenuItem;
|
||||
IBOutlet NSMenuItem* mCloseWindowMenuItem;
|
||||
|
@ -137,11 +136,12 @@
|
|||
-(IBAction) addFolder:(id)aSender;
|
||||
-(IBAction) addSeparator:(id)aSender;
|
||||
|
||||
//Window menu actions
|
||||
// Window menu actions
|
||||
-(IBAction) newTab:(id)aSender;
|
||||
-(IBAction) closeTab:(id)aSender;
|
||||
-(IBAction) downloadsWindow:(id)aSender;
|
||||
|
||||
//Help menu actions
|
||||
// Help menu actions
|
||||
-(IBAction) infoLink:(id)aSender;
|
||||
-(IBAction) feedbackLink:(id)aSender;
|
||||
|
||||
|
@ -154,7 +154,8 @@
|
|||
|
||||
- (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost;
|
||||
|
||||
-(NSWindow*)getFrontmostBrowserWindow;
|
||||
- (NSView*)getSavePanelView;
|
||||
- (NSWindow*)getFrontmostBrowserWindow;
|
||||
|
||||
- (MVPreferencesController *)preferencesController;
|
||||
- (void)displayPreferencesWindow:sender;
|
||||
|
|
|
@ -260,19 +260,7 @@ const int kReuseWindowOnAE = 2;
|
|||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
if ([ProgressDlgController numDownloadInProgress] > 0)
|
||||
{
|
||||
NSString *alert = NSLocalizedString(@"QuitWithDownloadsMsg", @"Really Quit?");
|
||||
NSString *message = NSLocalizedString(@"QuitWithDownloadsExpl", @"");
|
||||
NSString *okButton = NSLocalizedString(@"QuitWithdownloadsButtonDefault",@"Cancel");
|
||||
NSString *altButton = NSLocalizedString(@"QuitWithdownloadsButtonAlt",@"Quit");
|
||||
// while the panel is up, download dialogs won't update (no timers firing) but
|
||||
// downloads continue (PLEvents being processed)
|
||||
if (NSRunAlertPanel(alert, message, okButton, altButton, nil) == NSAlertDefaultReturn)
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
return NSTerminateNow;
|
||||
return [[ProgressDlgController sharedDownloadController] allowTerminate];
|
||||
}
|
||||
|
||||
-(void)applicationWillTerminate: (NSNotification*)aNotification
|
||||
|
@ -439,7 +427,7 @@ const int kReuseWindowOnAE = 2;
|
|||
{
|
||||
BrowserWindowController* browserController = [self getMainWindowBrowserController];
|
||||
if (browserController)
|
||||
[browserController saveDocument:NO filterView:mFilterView filterList: mFilterList];
|
||||
[browserController saveDocument:NO filterView:mFilterView];
|
||||
}
|
||||
|
||||
-(IBAction) pageSetup:(id)aSender
|
||||
|
@ -584,6 +572,11 @@ const int kReuseWindowOnAE = 2;
|
|||
}
|
||||
}
|
||||
|
||||
-(IBAction) downloadsWindow:(id)aSender
|
||||
{
|
||||
[[ProgressDlgController sharedDownloadController] showWindow:aSender];
|
||||
}
|
||||
|
||||
- (void)adjustBookmarksMenuItemsEnabling:(BOOL)inBrowserWindowFrontmost;
|
||||
{
|
||||
[mAddBookmarkMenuItem setEnabled:inBrowserWindowFrontmost];
|
||||
|
@ -591,6 +584,11 @@ const int kReuseWindowOnAE = 2;
|
|||
[mCreateBookmarksSeparatorMenuItem setEnabled:NO]; // separators are not implemented yet
|
||||
}
|
||||
|
||||
- (NSView*)getSavePanelView
|
||||
{
|
||||
return mFilterView;
|
||||
}
|
||||
|
||||
-(NSWindow*)getFrontmostBrowserWindow
|
||||
{
|
||||
// for some reason, [NSApp mainWindow] doesn't always work, so we have to
|
||||
|
|
|
@ -47,7 +47,58 @@ NSGETMODULE(_name) (nsIComponentManager* aCompMgr, \
|
|||
}
|
||||
|
||||
// NSGetModule entry points
|
||||
DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsUCvJAModule) DECL_NSGETMODULE(nsUCvCnModule) DECL_NSGETMODULE(nsUCvLatinModule) DECL_NSGETMODULE(nsUCvTWModule) DECL_NSGETMODULE(nsUCvTW2Module) DECL_NSGETMODULE(nsUCvKoModule) DECL_NSGETMODULE(nsLocaleModule) DECL_NSGETMODULE(nsStringBundleModule) DECL_NSGETMODULE(nsLWBrkModule) DECL_NSGETMODULE(nsCharDetModule) DECL_NSGETMODULE(xpconnect) DECL_NSGETMODULE(cacheservice) DECL_NSGETMODULE(necko_core_and_primary_protocols) DECL_NSGETMODULE(necko_secondary_protocols) DECL_NSGETMODULE(nsURILoaderModule) DECL_NSGETMODULE(nsPrefModule) DECL_NSGETMODULE(nsCJVMManagerModule) DECL_NSGETMODULE(nsSecurityManagerModule) DECL_NSGETMODULE(nsChromeModule) DECL_NSGETMODULE(nsRDFModule) DECL_NSGETMODULE(nsParserModule) DECL_NSGETMODULE(nsGfxMacModule) DECL_NSGETMODULE(nsGfx2Module) DECL_NSGETMODULE(nsImageLib2Module) DECL_NSGETMODULE(nsPNGDecoderModule) DECL_NSGETMODULE(nsGIFModule2) DECL_NSGETMODULE(nsJPEGDecoderModule) DECL_NSGETMODULE(nsPluginModule) DECL_NSGETMODULE(javascript__protocol) DECL_NSGETMODULE(DOM_components) DECL_NSGETMODULE(nsViewModule) DECL_NSGETMODULE(nsWidgetMacModule) DECL_NSGETMODULE(nsContentModule) DECL_NSGETMODULE(nsLayoutModule) DECL_NSGETMODULE(nsMorkModule) DECL_NSGETMODULE(docshell_provider) DECL_NSGETMODULE(embedcomponents) DECL_NSGETMODULE(Browser_Embedding_Module) DECL_NSGETMODULE(nsEditorModule) DECL_NSGETMODULE(nsTransactionManagerModule) DECL_NSGETMODULE(nsTextServicesModule) DECL_NSGETMODULE(nsProfileModule) DECL_NSGETMODULE(Session_History_Module) DECL_NSGETMODULE(application) DECL_NSGETMODULE(nsCookieModule) DECL_NSGETMODULE(nsXMLExtrasModule) DECL_NSGETMODULE(nsUniversalCharDetModule) DECL_NSGETMODULE(BOOT) DECL_NSGETMODULE(NSS)
|
||||
DECL_NSGETMODULE(UcharUtil)
|
||||
DECL_NSGETMODULE(nsUConvModule)
|
||||
DECL_NSGETMODULE(nsUCvJAModule)
|
||||
DECL_NSGETMODULE(nsUCvCnModule)
|
||||
DECL_NSGETMODULE(nsUCvLatinModule)
|
||||
DECL_NSGETMODULE(nsUCvTWModule)
|
||||
DECL_NSGETMODULE(nsUCvTW2Module)
|
||||
DECL_NSGETMODULE(nsUCvKoModule)
|
||||
DECL_NSGETMODULE(nsLocaleModule)
|
||||
DECL_NSGETMODULE(nsStringBundleModule)
|
||||
DECL_NSGETMODULE(nsLWBrkModule)
|
||||
DECL_NSGETMODULE(nsCharDetModule)
|
||||
DECL_NSGETMODULE(xpconnect)
|
||||
DECL_NSGETMODULE(cacheservice)
|
||||
DECL_NSGETMODULE(necko_core_and_primary_protocols)
|
||||
DECL_NSGETMODULE(necko_secondary_protocols)
|
||||
DECL_NSGETMODULE(nsURILoaderModule)
|
||||
DECL_NSGETMODULE(nsPrefModule)
|
||||
DECL_NSGETMODULE(nsCJVMManagerModule)
|
||||
DECL_NSGETMODULE(nsSecurityManagerModule)
|
||||
DECL_NSGETMODULE(nsChromeModule)
|
||||
DECL_NSGETMODULE(nsRDFModule)
|
||||
DECL_NSGETMODULE(nsParserModule)
|
||||
DECL_NSGETMODULE(nsGfxMacModule)
|
||||
DECL_NSGETMODULE(nsGfx2Module)
|
||||
DECL_NSGETMODULE(nsImageLib2Module)
|
||||
DECL_NSGETMODULE(nsPNGDecoderModule)
|
||||
DECL_NSGETMODULE(nsGIFModule2)
|
||||
DECL_NSGETMODULE(nsJPEGDecoderModule)
|
||||
DECL_NSGETMODULE(nsPluginModule)
|
||||
DECL_NSGETMODULE(javascript__protocol)
|
||||
DECL_NSGETMODULE(JS_component_loader)
|
||||
DECL_NSGETMODULE(DOM_components)
|
||||
DECL_NSGETMODULE(nsViewModule)
|
||||
DECL_NSGETMODULE(nsWidgetMacModule)
|
||||
DECL_NSGETMODULE(nsContentModule)
|
||||
DECL_NSGETMODULE(nsLayoutModule)
|
||||
DECL_NSGETMODULE(nsMorkModule)
|
||||
DECL_NSGETMODULE(docshell_provider)
|
||||
DECL_NSGETMODULE(embedcomponents)
|
||||
DECL_NSGETMODULE(Browser_Embedding_Module)
|
||||
DECL_NSGETMODULE(nsEditorModule)
|
||||
DECL_NSGETMODULE(nsTransactionManagerModule)
|
||||
DECL_NSGETMODULE(nsTextServicesModule)
|
||||
DECL_NSGETMODULE(nsProfileModule)
|
||||
DECL_NSGETMODULE(Session_History_Module)
|
||||
DECL_NSGETMODULE(application)
|
||||
DECL_NSGETMODULE(nsCookieModule)
|
||||
DECL_NSGETMODULE(nsXMLExtrasModule)
|
||||
DECL_NSGETMODULE(nsUniversalCharDetModule)
|
||||
DECL_NSGETMODULE(BOOT)
|
||||
DECL_NSGETMODULE(NSS)
|
||||
#line 52 "nsStaticComponents.cpp.in"
|
||||
|
||||
/**
|
||||
|
@ -55,7 +106,58 @@ DECL_NSGETMODULE(UcharUtil) DECL_NSGETMODULE(nsUConvModule) DECL_NSGETMODULE(nsU
|
|||
*/
|
||||
static nsStaticModuleInfo gStaticModuleInfo[] = {
|
||||
#define MODULE(_name) { (#_name), NSGETMODULE(_name) }
|
||||
MODULE(UcharUtil), MODULE(nsUConvModule), MODULE(nsUCvJAModule), MODULE(nsUCvCnModule), MODULE(nsUCvLatinModule), MODULE(nsUCvTWModule), MODULE(nsUCvTW2Module), MODULE(nsUCvKoModule), MODULE(nsLocaleModule), MODULE(nsStringBundleModule), MODULE(nsLWBrkModule), MODULE(nsCharDetModule), MODULE(xpconnect), MODULE(cacheservice), MODULE(necko_core_and_primary_protocols), MODULE(necko_secondary_protocols), MODULE(nsURILoaderModule), MODULE(nsPrefModule), MODULE(nsCJVMManagerModule), MODULE(nsSecurityManagerModule), MODULE(nsChromeModule), MODULE(nsRDFModule), MODULE(nsParserModule), MODULE(nsGfxMacModule), MODULE(nsGfx2Module), MODULE(nsImageLib2Module), MODULE(nsPNGDecoderModule), MODULE(nsGIFModule2), MODULE(nsJPEGDecoderModule), MODULE(nsPluginModule), MODULE(javascript__protocol), MODULE(DOM_components), MODULE(nsViewModule), MODULE(nsWidgetMacModule), MODULE(nsContentModule), MODULE(nsLayoutModule), MODULE(nsMorkModule), MODULE(docshell_provider), MODULE(embedcomponents), MODULE(Browser_Embedding_Module), MODULE(nsEditorModule), MODULE(nsTransactionManagerModule), MODULE(nsTextServicesModule), MODULE(nsProfileModule), MODULE(Session_History_Module), MODULE(application), MODULE(nsCookieModule), MODULE(nsXMLExtrasModule), MODULE(nsUniversalCharDetModule), MODULE(BOOT), MODULE(NSS),
|
||||
MODULE(UcharUtil),
|
||||
MODULE(nsUConvModule),
|
||||
MODULE(nsUCvJAModule),
|
||||
MODULE(nsUCvCnModule),
|
||||
MODULE(nsUCvLatinModule),
|
||||
MODULE(nsUCvTWModule),
|
||||
MODULE(nsUCvTW2Module),
|
||||
MODULE(nsUCvKoModule),
|
||||
MODULE(nsLocaleModule),
|
||||
MODULE(nsStringBundleModule),
|
||||
MODULE(nsLWBrkModule),
|
||||
MODULE(nsCharDetModule),
|
||||
MODULE(xpconnect),
|
||||
MODULE(cacheservice),
|
||||
MODULE(necko_core_and_primary_protocols),
|
||||
MODULE(necko_secondary_protocols),
|
||||
MODULE(nsURILoaderModule),
|
||||
MODULE(nsPrefModule),
|
||||
MODULE(nsCJVMManagerModule),
|
||||
MODULE(nsSecurityManagerModule),
|
||||
MODULE(nsChromeModule),
|
||||
MODULE(nsRDFModule),
|
||||
MODULE(nsParserModule),
|
||||
MODULE(nsGfxMacModule),
|
||||
MODULE(nsGfx2Module),
|
||||
MODULE(nsImageLib2Module),
|
||||
MODULE(nsPNGDecoderModule),
|
||||
MODULE(nsGIFModule2),
|
||||
MODULE(nsJPEGDecoderModule),
|
||||
MODULE(nsPluginModule),
|
||||
MODULE(javascript__protocol),
|
||||
MODULE(JS_component_loader),
|
||||
MODULE(DOM_components),
|
||||
MODULE(nsViewModule),
|
||||
MODULE(nsWidgetMacModule),
|
||||
MODULE(nsContentModule),
|
||||
MODULE(nsLayoutModule),
|
||||
MODULE(nsMorkModule),
|
||||
MODULE(docshell_provider),
|
||||
MODULE(embedcomponents),
|
||||
MODULE(Browser_Embedding_Module),
|
||||
MODULE(nsEditorModule),
|
||||
MODULE(nsTransactionManagerModule),
|
||||
MODULE(nsTextServicesModule),
|
||||
MODULE(nsProfileModule),
|
||||
MODULE(Session_History_Module),
|
||||
MODULE(application),
|
||||
MODULE(nsCookieModule),
|
||||
MODULE(nsXMLExtrasModule),
|
||||
MODULE(nsUniversalCharDetModule),
|
||||
MODULE(BOOT),
|
||||
MODULE(NSS),
|
||||
#line 60 "nsStaticComponents.cpp.in"
|
||||
};
|
||||
|
||||
|
|
|
@ -1,883 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the NPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the NPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "NSString+Utils.h"
|
||||
|
||||
#import "BookmarksDataSource.h"
|
||||
#import "BookmarkInfoController.h"
|
||||
#import "SiteIconProvider.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsINamespaceManager.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
#import "BookmarksService.h"
|
||||
|
||||
@interface BookmarksDataSource(Private)
|
||||
|
||||
- (void)restoreFolderExpandedStates;
|
||||
- (void)refreshChildrenOfItem:(nsIContent*)item;
|
||||
|
||||
@end
|
||||
|
||||
const int kBookmarksRootItemTag = -2;
|
||||
|
||||
@implementation BookmarksDataSource
|
||||
|
||||
-(id) init
|
||||
{
|
||||
if ( (self = [super init]) )
|
||||
{
|
||||
mCachedHref = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// NSLog(@"BookmarksDataSource dealloc");
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
-(void) awakeFromNib
|
||||
{
|
||||
// make sure these are disabled at the start since the outliner
|
||||
// starts off with no selection.
|
||||
[mEditBookmarkButton setEnabled:NO];
|
||||
[mDeleteBookmarkButton setEnabled:NO];
|
||||
}
|
||||
|
||||
-(void) windowClosing
|
||||
{
|
||||
BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManagerDontAlloc];
|
||||
[bmManager removeBookmarksClient:self];
|
||||
}
|
||||
|
||||
-(void) ensureBookmarks
|
||||
{
|
||||
if (mRegisteredClient)
|
||||
return;
|
||||
|
||||
BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManager];
|
||||
[bmManager addBookmarksClient:self];
|
||||
mRegisteredClient = YES;
|
||||
|
||||
[mOutlineView setTarget: self];
|
||||
[mOutlineView setDoubleAction: @selector(openBookmark:)];
|
||||
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
|
||||
[mOutlineView reloadData];
|
||||
[self restoreFolderExpandedStates];
|
||||
}
|
||||
|
||||
-(IBAction)addBookmark:(id)aSender
|
||||
{
|
||||
[self addBookmark: aSender useSelection: YES isFolder: NO URL:nil title:nil];
|
||||
}
|
||||
|
||||
-(IBAction)addFolder:(id)aSender
|
||||
{
|
||||
[self addBookmark: aSender useSelection: YES isFolder: YES URL:nil title:nil];
|
||||
}
|
||||
|
||||
-(void)addBookmark:(id)aSender useSelection:(BOOL)aUseSel isFolder:(BOOL)aIsFolder URL:(NSString*)aURL title:(NSString*)aTitle
|
||||
{
|
||||
// We use the selected item to determine the parent only if aUseSel is YES.
|
||||
BookmarkItem* item = nil;
|
||||
if (aUseSel && ([mOutlineView numberOfSelectedRows] == 1))
|
||||
{
|
||||
// There is only one selected row. If it is a folder, use it as our parent.
|
||||
// Otherwise, use our parent,
|
||||
int index = [mOutlineView selectedRow];
|
||||
item = [mOutlineView itemAtRow: index];
|
||||
if (![mOutlineView isExpandable: item]) {
|
||||
// We can't be used as the parent. Try our parent.
|
||||
nsIContent* content = [item contentNode];
|
||||
if (!content)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
content->GetParent(*getter_AddRefs(parentContent));
|
||||
nsCOMPtr<nsIContent> root;
|
||||
BookmarksService::GetRootContent(getter_AddRefs(root));
|
||||
|
||||
// The root has no item, so we don't need to do a lookup unless we
|
||||
// aren't the root.
|
||||
if (parentContent != root) {
|
||||
PRUint32 contentID;
|
||||
parentContent->GetContentID(&contentID);
|
||||
item = BookmarksService::GetWrapperFor(contentID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[self addBookmark:aSender withParent:item isFolder:aIsFolder URL:aURL title:aTitle];
|
||||
}
|
||||
|
||||
-(void)addBookmark:(id)aSender withParent:(BookmarkItem*)bmItem isFolder:(BOOL)aIsFolder URL:(NSString*)aURL title:(NSString*)aTitle
|
||||
{
|
||||
NSString* titleString = aTitle;
|
||||
NSString* urlString = aURL;
|
||||
|
||||
if (!aIsFolder)
|
||||
{
|
||||
// If no URL and title were specified, get them from the current page.
|
||||
if (!aURL || !aTitle)
|
||||
[[mBrowserWindowController getBrowserWrapper] getTitle:&titleString andHref:&urlString];
|
||||
|
||||
mCachedHref = [NSString stringWithString:urlString];
|
||||
[mCachedHref retain];
|
||||
|
||||
} else { // Folder
|
||||
mCachedHref = nil;
|
||||
titleString = NSLocalizedString(@"NewBookmarkFolder", @"");
|
||||
}
|
||||
|
||||
NSTextField* textField = [mBrowserWindowController getAddBookmarkTitle];
|
||||
NSString* bookmarkTitle = titleString;
|
||||
NSString* cleanedTitle = [bookmarkTitle stringByReplacingCharactersInSet:[NSCharacterSet controlCharacterSet] withString:@" "];
|
||||
|
||||
[textField setStringValue: cleanedTitle];
|
||||
|
||||
[mBrowserWindowController cacheBookmarkDS: self];
|
||||
|
||||
// Show/hide the bookmark all tabs checkbox as appropriate.
|
||||
NSTabView* tabView = [mBrowserWindowController getTabBrowser];
|
||||
id checkbox = [mBrowserWindowController getAddBookmarkCheckbox];
|
||||
BOOL hasSuperview = [checkbox superview] != nil;
|
||||
if (aIsFolder && hasSuperview) {
|
||||
// Just don't show it at all.
|
||||
[checkbox removeFromSuperview];
|
||||
[checkbox retain];
|
||||
}
|
||||
else if (!aIsFolder && !hasSuperview) {
|
||||
// Put it back in.
|
||||
[[[mBrowserWindowController getAddBookmarkSheetWindow] contentView] addSubview: checkbox];
|
||||
[checkbox autorelease];
|
||||
}
|
||||
|
||||
// Enable the bookmark all tabs checkbox if appropriate.
|
||||
if (!aIsFolder)
|
||||
[[mBrowserWindowController getAddBookmarkCheckbox] setEnabled: ([tabView numberOfTabViewItems] > 1)];
|
||||
|
||||
// Build up the folder list.
|
||||
NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder];
|
||||
[popup removeAllItems];
|
||||
[popup addItemWithTitle: NSLocalizedString(@"BookmarksRootName", @"")];
|
||||
[[popup lastItem] setTag:kBookmarksRootItemTag];
|
||||
|
||||
BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManager];
|
||||
[bmManager buildFlatFolderList:[popup menu] fromRoot:NULL];
|
||||
|
||||
int itemIndex = [popup indexOfItemWithTag:[bmItem intContentID]];
|
||||
if (itemIndex != -1)
|
||||
[popup selectItemAtIndex:itemIndex];
|
||||
|
||||
[popup synchronizeTitleAndSelectedItem];
|
||||
|
||||
[NSApp beginSheet: [mBrowserWindowController getAddBookmarkSheetWindow]
|
||||
modalForWindow: [mBrowserWindowController window]
|
||||
modalDelegate: nil //self
|
||||
didEndSelector: nil //@selector(sheetDidEnd:)
|
||||
contextInfo: nil];
|
||||
}
|
||||
|
||||
-(void)endAddBookmark: (int)aCode
|
||||
{
|
||||
if (aCode == 0)
|
||||
return;
|
||||
|
||||
BOOL isGroup = NO;
|
||||
id checkbox = [mBrowserWindowController getAddBookmarkCheckbox];
|
||||
if (([checkbox superview] != nil) && [checkbox isEnabled] && ([checkbox state] == NSOnState))
|
||||
{
|
||||
[mCachedHref release];
|
||||
mCachedHref = nil;
|
||||
isGroup = YES;
|
||||
}
|
||||
|
||||
BookmarksManager* bmManager = [BookmarksManager sharedBookmarksManager];
|
||||
NSString* titleString = [[mBrowserWindowController getAddBookmarkTitle] stringValue];
|
||||
|
||||
// Figure out the parent element.
|
||||
nsCOMPtr<nsIContent> parentContent;
|
||||
|
||||
NSPopUpButton* popup = [mBrowserWindowController getAddBookmarkFolder];
|
||||
NSMenuItem* selectedItem = [popup selectedItem];
|
||||
int tag = [selectedItem tag];
|
||||
if (tag != kBookmarksRootItemTag)
|
||||
{
|
||||
BookmarkItem* item = BookmarksService::GetWrapperFor(tag);
|
||||
// Get the content node.
|
||||
parentContent = [item contentNode];
|
||||
}
|
||||
|
||||
if (isGroup)
|
||||
{
|
||||
id tabBrowser = [mBrowserWindowController getTabBrowser];
|
||||
int count = [tabBrowser numberOfTabViewItems];
|
||||
|
||||
NSMutableArray* itemsArray = [[NSMutableArray alloc] initWithCapacity:count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
BrowserWrapper* browserWrapper = (BrowserWrapper*)[[tabBrowser tabViewItemAtIndex: i] view];
|
||||
|
||||
NSString* titleString = nil;
|
||||
NSString* hrefString = nil;
|
||||
[browserWrapper getTitle:&titleString andHref:&hrefString];
|
||||
|
||||
NSDictionary* itemDict = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
titleString, @"title",
|
||||
hrefString, @"href",
|
||||
nil];
|
||||
[itemsArray addObject:itemDict];
|
||||
}
|
||||
|
||||
[bmManager addNewBookmarkGroup:titleString items:itemsArray withParent:parentContent];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mCachedHref)
|
||||
{
|
||||
[bmManager addNewBookmark:mCachedHref title:titleString withParent:parentContent];
|
||||
[mCachedHref release];
|
||||
mCachedHref = nil;
|
||||
}
|
||||
else
|
||||
[bmManager addNewBookmarkFolder:titleString withParent:parentContent];
|
||||
}
|
||||
}
|
||||
|
||||
-(IBAction)deleteBookmarks: (id)aSender
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
// first, see how many items are selected
|
||||
BOOL haveBookmarks = NO;
|
||||
|
||||
NSEnumerator* testSelRows = [mOutlineView selectedRowEnumerator];
|
||||
for (NSNumber* currIndex = [testSelRows nextObject];
|
||||
currIndex != nil;
|
||||
currIndex = [testSelRows nextObject])
|
||||
{
|
||||
index = [currIndex intValue];
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
if ([mOutlineView isExpandable: item]) {
|
||||
// dumb check to see if we're deleting an empty folder. Should really
|
||||
// recurse down
|
||||
if ([self outlineView:mOutlineView numberOfChildrenOfItem: item] > 0)
|
||||
haveBookmarks = YES;
|
||||
} else
|
||||
haveBookmarks = YES;
|
||||
}
|
||||
|
||||
// ideally, we should count the number of doomed bookmarks and tell the user
|
||||
if (haveBookmarks) {
|
||||
NSString *alert = NSLocalizedString(@"DeteleBookmarksAlert",@"");
|
||||
NSString *message = NSLocalizedString(@"DeteleBookmarksMsg",@"");
|
||||
NSString *okButton = NSLocalizedString(@"DeteleBookmarksOKButton",@"");
|
||||
NSString *cancelButton = NSLocalizedString(@"DeteleBookmarksCancelButton",@"");
|
||||
if (NSRunAlertPanel(alert, message, okButton, cancelButton, nil) != NSAlertDefaultReturn)
|
||||
return;
|
||||
}
|
||||
|
||||
// The alert panel was the key window. As soon as we dismissed it, Cocoa will
|
||||
// pick a new one for us. Ideally, it'll be the window we were using when
|
||||
// we clicked the delete button. However, if by chance the BookmarkInfoController
|
||||
// is visible, it will become the key window since it's a panel. If we then delete
|
||||
// the bookmark and try to close the window before we've setup a new bookmark,
|
||||
// we'll trigger the windowDidResignKey message, which will try to update the bookmark
|
||||
// we just deleted, and things will crash. So, we'll trigger windowDidResignKey now
|
||||
// and avoid the unpleasentness of a crash log.
|
||||
|
||||
if (![[mBrowserWindowController window] isKeyWindow])
|
||||
[[mBrowserWindowController window] makeKeyWindow];
|
||||
|
||||
// we'll run into problems if a parent item and one if its children are both selected.
|
||||
// A cheap way of having to avoid scanning the list to remove children is to have the
|
||||
// outliner collapse all items that are being deleted. This will cull the selection
|
||||
// for us and eliminate any children that happened to be selected.
|
||||
NSEnumerator* selRows = [mOutlineView selectedRowEnumerator];
|
||||
for (NSNumber* currIndex = [selRows nextObject];
|
||||
currIndex != nil;
|
||||
currIndex = [selRows nextObject]) {
|
||||
index = [currIndex intValue];
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
[mOutlineView collapseItem: item];
|
||||
}
|
||||
|
||||
// create array of items we need to delete. Deleting items out of of the
|
||||
// selection array is problematic for some reason.
|
||||
NSMutableArray* itemsToDelete = [[[NSMutableArray alloc] init] autorelease];
|
||||
selRows = [mOutlineView selectedRowEnumerator];
|
||||
for (NSNumber* currIndex = [selRows nextObject];
|
||||
currIndex != nil;
|
||||
currIndex = [selRows nextObject]) {
|
||||
index = [currIndex intValue];
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
[itemsToDelete addObject: item];
|
||||
}
|
||||
|
||||
// delete all bookmarks that are in our array
|
||||
int count = [itemsToDelete count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
BookmarkItem* item = [itemsToDelete objectAtIndex: i];
|
||||
[self deleteBookmark: item];
|
||||
}
|
||||
|
||||
// restore selection to location near last item deleted or last item
|
||||
int total = [mOutlineView numberOfRows];
|
||||
if (index >= total)
|
||||
index = total - 1;
|
||||
[mOutlineView selectRow: index byExtendingSelection: NO];
|
||||
// lame, but makes sure we catch all delete events in Info Panel
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"NSOutlineViewSelectionDidChangeNotification" object:mOutlineView];
|
||||
}
|
||||
|
||||
-(void)deleteBookmark:(id)aItem
|
||||
{
|
||||
[aItem remove];
|
||||
}
|
||||
|
||||
-(IBAction)openBookmark: (id)aSender
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
id item = [mOutlineView itemAtRow: index];
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
if ([item isGroup])
|
||||
{
|
||||
NSArray* groupURLs = [[BookmarksManager sharedBookmarksManager] getBookmarkGroupURIs:item];
|
||||
[mBrowserWindowController openTabGroup:groupURLs replaceExistingTabs:YES];
|
||||
}
|
||||
else if ([mOutlineView isExpandable: item])
|
||||
{
|
||||
if ([mOutlineView isItemExpanded: item])
|
||||
[mOutlineView collapseItem: item];
|
||||
else
|
||||
[mOutlineView expandItem: item];
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the command key is down, follow the command-click pref
|
||||
if (([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) &&
|
||||
[[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.opentabfor.middleclick" withSuccess:NULL])
|
||||
{
|
||||
BOOL loadInBackground = [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.loadInBackground" withSuccess:NULL];
|
||||
[mBrowserWindowController openNewTabWithURL:[item url] referrer:nil loadInBackground: loadInBackground];
|
||||
}
|
||||
else
|
||||
[[mBrowserWindowController getBrowserWrapper] loadURI:[item url] referrer:nil flags:NSLoadFlagsNone activate:YES];
|
||||
}
|
||||
}
|
||||
|
||||
-(IBAction)openBookmarkInNewTab:(id)aSender
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
return;
|
||||
|
||||
if ([mOutlineView numberOfSelectedRows] == 1)
|
||||
{
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
BOOL loadInBackground = [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.loadInBackground" withSuccess:NULL];
|
||||
[mBrowserWindowController openNewTabWithURL:[item url] referrer:nil loadInBackground: loadInBackground];
|
||||
}
|
||||
}
|
||||
|
||||
-(IBAction)openBookmarkInNewWindow:(id)aSender
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
return;
|
||||
if ([mOutlineView numberOfSelectedRows] == 1)
|
||||
{
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
|
||||
BOOL loadInBackground = [[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.loadInBackground" withSuccess:NULL];
|
||||
|
||||
if ([item isGroup])
|
||||
[mBrowserWindowController openNewWindowWithGroup:[item contentNode] loadInBackground:loadInBackground];
|
||||
else
|
||||
[mBrowserWindowController openNewWindowWithURL:[item url] referrer: nil loadInBackground: loadInBackground];
|
||||
}
|
||||
}
|
||||
|
||||
-(IBAction)showBookmarkInfo:(id)aSender
|
||||
{
|
||||
BookmarkInfoController *bic = [BookmarkInfoController sharedBookmarkInfoController];
|
||||
|
||||
int index = [mOutlineView selectedRow];
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
[bic setBookmark:item];
|
||||
|
||||
[bic showWindow:bic];
|
||||
}
|
||||
|
||||
- (void)restoreFolderExpandedStates
|
||||
{
|
||||
int curRow = 0;
|
||||
|
||||
while (curRow < [mOutlineView numberOfRows])
|
||||
{
|
||||
id item = [mOutlineView itemAtRow:curRow];
|
||||
|
||||
if (item)
|
||||
{
|
||||
nsCOMPtr<nsIContent> content;
|
||||
content = [item contentNode];
|
||||
|
||||
PRBool isOpen = content && content->HasAttr(kNameSpaceID_None, BookmarksService::gOpenAtom);
|
||||
if (isOpen)
|
||||
[mOutlineView expandItem: item];
|
||||
else
|
||||
[mOutlineView collapseItem: item];
|
||||
}
|
||||
|
||||
curRow ++;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshChildrenOfItem:(nsIContent*)item
|
||||
{
|
||||
BookmarkItem* bmItem = nil;
|
||||
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
if (item)
|
||||
item->GetParent(*getter_AddRefs(parent));
|
||||
if (parent) // we're not the root
|
||||
bmItem = [[BookmarksManager sharedBookmarksManager] getWrapperForContent:item];
|
||||
|
||||
[self reloadDataForItem:bmItem reloadChildren:YES];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
// BookmarksClient protocol
|
||||
|
||||
- (void)bookmarkAdded:(nsIContent*)bookmark inContainer:(nsIContent*)container isChangedRoot:(BOOL)isRoot
|
||||
{
|
||||
[self refreshChildrenOfItem:container];
|
||||
}
|
||||
|
||||
- (void)bookmarkRemoved:(nsIContent*)bookmark inContainer:(nsIContent*)container isChangedRoot:(BOOL)isRoot
|
||||
{
|
||||
[self refreshChildrenOfItem:container];
|
||||
}
|
||||
|
||||
- (void)bookmarkChanged:(nsIContent*)bookmark
|
||||
{
|
||||
BookmarkItem* item = [[BookmarksManager sharedBookmarksManager] getWrapperForContent:bookmark];
|
||||
[self reloadDataForItem:item reloadChildren:NO];
|
||||
}
|
||||
|
||||
- (void)specialFolder:(EBookmarksFolderType)folderType changedTo:(nsIContent*)newFolderContent
|
||||
{
|
||||
// change the icons
|
||||
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
//
|
||||
// outlineView:shouldEditTableColumn:item: (delegate method)
|
||||
//
|
||||
// Called by the outliner to determine whether or not we should allow the
|
||||
// user to edit this item. We're leaving it off for now, becaue there are
|
||||
// some usability issues with inline editing (no undo, Escape doesn't work).
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView shouldEditTableColumn:(NSTableColumn *)tableColumn item:(id)item
|
||||
{
|
||||
return NO; //([[tableColumn identifier] isEqualToString:@"name"]);
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView child:(int)index ofItem:(id)item
|
||||
{
|
||||
if (!mRegisteredClient) return nil;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
if (!item)
|
||||
BookmarksService::GetRootContent(getter_AddRefs(content));
|
||||
else
|
||||
content = [item contentNode];
|
||||
|
||||
nsCOMPtr<nsIContent> child;
|
||||
content->ChildAt(index, *getter_AddRefs(child));
|
||||
if ( child )
|
||||
return BookmarksService::GetWrapperFor(child);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
|
||||
{
|
||||
if (!mRegisteredClient) return NO;
|
||||
|
||||
if (!item)
|
||||
return YES; // The root node is always open.
|
||||
|
||||
return [item isFolder];
|
||||
}
|
||||
|
||||
- (int)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
|
||||
{
|
||||
if (!mRegisteredClient) return 0;
|
||||
|
||||
nsCOMPtr<nsIContent> content;
|
||||
if (!item)
|
||||
BookmarksService::GetRootContent(getter_AddRefs(content));
|
||||
else
|
||||
content = [item contentNode];
|
||||
|
||||
PRInt32 childCount;
|
||||
content->ChildCount(childCount);
|
||||
|
||||
return childCount;
|
||||
}
|
||||
|
||||
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
if (!mRegisteredClient) return nil;
|
||||
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
NSMutableAttributedString *cellValue = nil;
|
||||
|
||||
if ([columnName isEqualToString: @"name"])
|
||||
{
|
||||
NSFileWrapper *fileWrapper = [[NSFileWrapper alloc] initRegularFileWithContents:nil];
|
||||
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] initWithFileWrapper:fileWrapper];
|
||||
|
||||
nsIContent* content = [item contentNode];
|
||||
nsAutoString nameAttr;
|
||||
content->GetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr);
|
||||
|
||||
//Set cell's textual contents
|
||||
//[cellValue replaceCharactersInRange:NSMakeRange(0, [cellValue length]) withString:[NSString stringWith_nsAString: nameAttr]];
|
||||
cellValue = [[NSMutableAttributedString alloc] initWithString:[NSString stringWith_nsAString: nameAttr]];
|
||||
|
||||
//Create an attributed string to hold the empty attachment, then release the components.
|
||||
NSMutableAttributedString* attachmentAttrString = [NSMutableAttributedString attributedStringWithAttachment:textAttachment];
|
||||
[textAttachment release];
|
||||
[fileWrapper release];
|
||||
|
||||
//Get the cell of the text attachment.
|
||||
NSCell* attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
|
||||
|
||||
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
|
||||
NSImage* bookmarkImage = BookmarksService::CreateIconForBookmark(elt);
|
||||
[attachmentAttrStringCell setImage:bookmarkImage];
|
||||
|
||||
//Insert the image
|
||||
[cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString];
|
||||
|
||||
//Tweak the baseline to vertically center the text.
|
||||
[cellValue addAttribute:NSBaselineOffsetAttributeName
|
||||
value:[NSNumber numberWithFloat:-3.0]
|
||||
range:NSMakeRange(0, 1)];
|
||||
}
|
||||
return cellValue;
|
||||
}
|
||||
|
||||
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
|
||||
{
|
||||
// object is really an NSString, even though objectValueForTableColumn returns NSAttributedStrings.
|
||||
NSString *columnName = [tableColumn identifier];
|
||||
if ( [columnName isEqualTo:@"name"] )
|
||||
{
|
||||
const unichar kAttachmentCharacter = NSAttachmentCharacter;
|
||||
|
||||
NSMutableString* mutableString = [NSMutableString stringWithString:object];
|
||||
[mutableString replaceOccurrencesOfString:[NSString stringWithCharacters:&kAttachmentCharacter length:1] withString:@"" options:0 range:NSMakeRange(0, [mutableString length])];
|
||||
|
||||
nsAutoString nameAttr;
|
||||
[mutableString assignTo_nsAString:nameAttr];
|
||||
|
||||
// stash it into the DOM
|
||||
BookmarkItem* bmItem = (BookmarkItem*)item;
|
||||
nsIContent* content = [bmItem contentNode];
|
||||
if (content)
|
||||
content->SetAttr(kNameSpaceID_None, BookmarksService::gNameAtom, nameAttr, PR_TRUE);
|
||||
|
||||
[bmItem itemChanged:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView *)ov writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard
|
||||
{
|
||||
if (!mRegisteredClient) return NO;
|
||||
|
||||
#ifdef FILTER_DESCENDANT_ON_DRAG
|
||||
NSArray *toDrag = BookmarksService::FilterOutDescendantsForDrag(items);
|
||||
#else
|
||||
NSArray *toDrag = items;
|
||||
#endif
|
||||
int count = [toDrag count];
|
||||
if (count > 0) {
|
||||
// Create Pasteboard Data
|
||||
NSMutableArray *draggedIDs = [NSMutableArray arrayWithCapacity: count];
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
[draggedIDs addObject: [[toDrag objectAtIndex: i] contentID]];
|
||||
|
||||
if (count == 1) {
|
||||
// if we have just one item, we add some more flavours
|
||||
[pboard declareTypes: [NSArray arrayWithObjects:
|
||||
@"MozBookmarkType", NSURLPboardType, NSStringPboardType, nil] owner: self];
|
||||
[pboard setPropertyList: draggedIDs forType: @"MozBookmarkType"];
|
||||
|
||||
NSString* itemURL = [[toDrag objectAtIndex: 0] url];
|
||||
[pboard setString:itemURL forType: NSStringPboardType];
|
||||
[[NSURL URLWithString:itemURL] writeToPasteboard: pboard];
|
||||
// maybe construct the @"MozURLType" type here also
|
||||
}
|
||||
else {
|
||||
// multiple bookmarks. Arrays of strings or NSURLs seem to
|
||||
// confuse receivers. Not sure what the correct way is.
|
||||
[pboard declareTypes: [NSArray arrayWithObject: @"MozBookmarkType"] owner: self];
|
||||
[pboard setPropertyList: draggedIDs forType: @"MozBookmarkType"];
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (NSDragOperation)outlineView:(NSOutlineView*)ov validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index
|
||||
{
|
||||
if (!mRegisteredClient) return NSDragOperationNone;
|
||||
|
||||
NSArray* types = [[info draggingPasteboard] types];
|
||||
BOOL isCopy = ([info draggingSourceOperationMask] == NSDragOperationCopy);
|
||||
|
||||
// if the index is -1, deny the drop
|
||||
if (index == NSOutlineViewDropOnItemIndex)
|
||||
return NSDragOperationNone;
|
||||
|
||||
if ([types containsObject: @"MozBookmarkType"])
|
||||
{
|
||||
NSArray *draggedIDs = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
|
||||
BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
return (BookmarksService::IsBookmarkDropValid(parent, index, draggedIDs, isCopy)) ? NSDragOperationGeneric : NSDragOperationNone;
|
||||
}
|
||||
|
||||
if ([types containsObject: @"MozURLType"])
|
||||
return NSDragOperationGeneric;
|
||||
|
||||
if ([types containsObject: NSStringPboardType])
|
||||
return NSDragOperationGeneric;
|
||||
|
||||
if ([types containsObject: NSURLPboardType])
|
||||
return NSDragOperationGeneric;
|
||||
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
- (BOOL)outlineView:(NSOutlineView*)ov acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index
|
||||
{
|
||||
if (!mRegisteredClient) return NO;
|
||||
|
||||
NSArray* types = [[info draggingPasteboard] types];
|
||||
BookmarkItem* parent = (item) ? item : BookmarksService::GetRootItem();
|
||||
BOOL isCopy = ([info draggingSourceOperationMask] == NSDragOperationCopy);
|
||||
|
||||
BookmarkItem* beforeItem = [self outlineView:ov child:index ofItem:item];
|
||||
if ([types containsObject: @"MozBookmarkType"])
|
||||
{
|
||||
NSArray *draggedItems = [[info draggingPasteboard] propertyListForType: @"MozBookmarkType"];
|
||||
return BookmarksService::PerformBookmarkDrop(parent, beforeItem, index, draggedItems, isCopy);
|
||||
}
|
||||
else if ([types containsObject: @"MozURLType"])
|
||||
{
|
||||
NSDictionary* proxy = [[info draggingPasteboard] propertyListForType: @"MozURLType"];
|
||||
return BookmarksService::PerformProxyDrop(parent, beforeItem, proxy);
|
||||
}
|
||||
else if ([types containsObject: NSStringPboardType])
|
||||
{
|
||||
NSString* draggedText = [[info draggingPasteboard] stringForType:NSStringPboardType];
|
||||
return BookmarksService::PerformURLDrop(parent, beforeItem, draggedText, draggedText);
|
||||
}
|
||||
else if ([types containsObject: NSURLPboardType])
|
||||
{
|
||||
NSURL* urlData = [NSURL URLFromPasteboard:[info draggingPasteboard]];
|
||||
return BookmarksService::PerformURLDrop(parent, beforeItem, [urlData absoluteString], [urlData absoluteString]);
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSString *)outlineView:(NSOutlineView *)outlineView tooltipStringForItem:(id)item
|
||||
{
|
||||
if (!mRegisteredClient) return @"";
|
||||
|
||||
NSString* descStr = nil;
|
||||
NSString* hrefStr = nil;
|
||||
nsIContent* content = [item contentNode];
|
||||
nsAutoString value;
|
||||
|
||||
content->GetAttr(kNameSpaceID_None, BookmarksService::gDescriptionAtom, value);
|
||||
if (value.Length())
|
||||
descStr = [NSString stringWith_nsAString:value];
|
||||
|
||||
// Only description for folders
|
||||
if ([item isFolder])
|
||||
return descStr;
|
||||
|
||||
// Extract the URL from the item
|
||||
content->GetAttr(kNameSpaceID_None, BookmarksService::gHrefAtom, value);
|
||||
if (value.Length())
|
||||
hrefStr = [NSString stringWith_nsAString:value];
|
||||
|
||||
if (!hrefStr)
|
||||
return descStr;
|
||||
else if (!descStr)
|
||||
return hrefStr;
|
||||
|
||||
// Display both URL and description
|
||||
return [NSString stringWithFormat:@"%@\n%@", hrefStr, descStr];
|
||||
}
|
||||
|
||||
/*
|
||||
- (NSMenu *)outlineView:(NSOutlineView *)outlineView contextMenuForItem:(id)item
|
||||
{
|
||||
// TODO - return (custom?) context menu for item here.
|
||||
// Note that according to HIG, there should never be disabled items in
|
||||
// a context menu - instead, items that do not apply should be removed.
|
||||
// We could nicely do that here.
|
||||
}
|
||||
*/
|
||||
|
||||
- (void)reloadDataForItem:(id)item reloadChildren: (BOOL)aReloadChildren
|
||||
{
|
||||
if (!item)
|
||||
[mOutlineView reloadData];
|
||||
else
|
||||
[mOutlineView reloadItem: item reloadChildren: aReloadChildren];
|
||||
}
|
||||
|
||||
- (BOOL)haveSelectedRow
|
||||
{
|
||||
return ([mOutlineView selectedRow] != -1);
|
||||
}
|
||||
|
||||
-(void)outlineViewSelectionDidChange: (NSNotification*) aNotification
|
||||
{
|
||||
BookmarkInfoController *bic = [BookmarkInfoController sharedBookmarkInfoController];
|
||||
int index = [mOutlineView selectedRow];
|
||||
if (index == -1)
|
||||
{
|
||||
[mEditBookmarkButton setEnabled:NO];
|
||||
[mDeleteBookmarkButton setEnabled:NO];
|
||||
[bic close];
|
||||
}
|
||||
else
|
||||
{
|
||||
BookmarkItem* item = [mOutlineView itemAtRow: index];
|
||||
|
||||
[mEditBookmarkButton setEnabled:YES];
|
||||
[mDeleteBookmarkButton setEnabled:![item isToobarRoot]];
|
||||
if ([[bic window] isVisible])
|
||||
[bic setBookmark:[mOutlineView itemAtRow:index]];
|
||||
}
|
||||
}
|
||||
|
||||
-(BOOL)validateMenuItem:(NSMenuItem*)aMenuItem
|
||||
{
|
||||
int index = [mOutlineView selectedRow];
|
||||
BOOL haveSelection = (index != -1);
|
||||
BOOL isBookmark = NO;
|
||||
BOOL isGroup = NO;
|
||||
|
||||
BookmarkItem* item = nil;
|
||||
|
||||
if (haveSelection)
|
||||
{
|
||||
item = [mOutlineView itemAtRow: index];
|
||||
isBookmark = ([mOutlineView isExpandable:item] == NO);
|
||||
isGroup = [item isGroup];
|
||||
}
|
||||
|
||||
// Bookmarks and Bookmark Groups can be opened in a new window
|
||||
if (([aMenuItem action] == @selector(openBookmarkInNewWindow:)))
|
||||
return (isBookmark || isGroup);
|
||||
|
||||
// Only Bookmarks can be opened in new tabs
|
||||
if (([aMenuItem action] == @selector(openBookmarkInNewTab:)))
|
||||
return isBookmark && [mBrowserWindowController newTabsAllowed];
|
||||
|
||||
if (([aMenuItem action] == @selector(showBookmarkInfo:)))
|
||||
return haveSelection;
|
||||
|
||||
if (([aMenuItem action] == @selector(deleteBookmarks:)))
|
||||
return haveSelection && ![item isToobarRoot]; // should deal with multiple selections
|
||||
|
||||
if (([aMenuItem action] == @selector(addFolder:)))
|
||||
return YES;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)outlineViewItemWillExpand:(NSNotification *)notification
|
||||
{
|
||||
BookmarkItem* item = [[notification userInfo] objectForKey:[[[notification userInfo] allKeys] objectAtIndex: 0]];
|
||||
[item contentNode]->SetAttr(kNameSpaceID_None, BookmarksService::gOpenAtom, NS_LITERAL_STRING("true"), PR_FALSE);
|
||||
}
|
||||
|
||||
- (void)outlineViewItemWillCollapse:(NSNotification *)notification
|
||||
{
|
||||
BookmarkItem* item = [[notification userInfo] objectForKey:[[[notification userInfo] allKeys] objectAtIndex: 0]];
|
||||
[item contentNode]->UnsetAttr(kNameSpaceID_None, BookmarksService::gOpenAtom, PR_FALSE);
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
@ -100,6 +100,7 @@
|
|||
|
||||
- (BOOL)isOpaque
|
||||
{
|
||||
// see http://developer.apple.com/qa/qa2001/qa1117.html
|
||||
if ( ([self tabViewType] == NSNoTabsBezelBorder) && (NSAppKitVersionNumber < 633) )
|
||||
return NO;
|
||||
|
||||
|
|
|
@ -1,94 +0,0 @@
|
|||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Chimera code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Simon Fraser <sfraser@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "BrowserWindow.h"
|
||||
#import "BrowserWindowController.h"
|
||||
#import "AutoCompleteTextField.h"
|
||||
|
||||
static const int kEscapeKeyCode = 53;
|
||||
|
||||
@implementation BrowserWindow
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)makeFirstResponder:(NSResponder*)responder
|
||||
{
|
||||
NSResponder* oldResponder = [self firstResponder];
|
||||
BOOL madeFirstResponder = [super makeFirstResponder:responder];
|
||||
if (madeFirstResponder && oldResponder != [self firstResponder])
|
||||
[(BrowserWindowController*)[self delegate] focusChangedFrom:oldResponder to:[self firstResponder]];
|
||||
return madeFirstResponder;
|
||||
}
|
||||
|
||||
- (void)sendEvent:(NSEvent *)theEvent
|
||||
{
|
||||
// We need this hack because NSWindow::sendEvent will eat the escape key
|
||||
// and won't pass it down to the key handler of responders in the window.
|
||||
// We have to override sendEvent for all of our escape key needs.
|
||||
if ([theEvent type] == NSKeyDown &&
|
||||
[theEvent keyCode] == kEscapeKeyCode && [self firstResponder] == [mAutoCompleteTextField fieldEditor])
|
||||
[mAutoCompleteTextField revertText];
|
||||
else
|
||||
[super sendEvent:theEvent];
|
||||
}
|
||||
|
||||
- (BOOL)suppressMakeKeyFront
|
||||
{
|
||||
return mSuppressMakeKeyFront;
|
||||
}
|
||||
|
||||
- (void)setSuppressMakeKeyFront:(BOOL)inSuppress
|
||||
{
|
||||
mSuppressMakeKeyFront = inSuppress;
|
||||
}
|
||||
|
||||
// accessor for the 'URL' Apple Event attribute
|
||||
- (NSString*)getURL
|
||||
{
|
||||
BrowserWindowController* windowController = (BrowserWindowController*)[self delegate];
|
||||
|
||||
NSString* titleString = nil;
|
||||
NSString* urlString = nil;
|
||||
|
||||
[[windowController getBrowserWrapper] getTitle:&titleString andHref:&urlString];
|
||||
return urlString;
|
||||
}
|
||||
|
||||
@end
|
|
@ -109,12 +109,12 @@ typedef enum
|
|||
IBOutlet NSTextField* mLocationSheetURLField;
|
||||
IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock
|
||||
IBOutlet PageProxyIcon* mProxyIcon;
|
||||
IBOutlet BrowserContentView* mContentView;
|
||||
IBOutlet BrowserContentView* mContentView;
|
||||
|
||||
IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource;
|
||||
IBOutlet HistoryDataSource* mHistoryDataSource;
|
||||
IBOutlet HistoryDataSource* mHistoryDataSource;
|
||||
|
||||
IBOutlet BookmarksToolbar* mPersonalToolbar;
|
||||
IBOutlet BookmarksToolbar* mPersonalToolbar;
|
||||
|
||||
IBOutlet NSWindow* mAddBookmarkSheetWindow;
|
||||
IBOutlet NSTextField* mAddBookmarkTitleField;
|
||||
|
@ -191,6 +191,8 @@ typedef enum
|
|||
- (void)updateLocationFields:(NSString *)locationString;
|
||||
- (void)updateSiteIcons:(NSImage *)siteIconImage;
|
||||
- (void)updateToolbarItems;
|
||||
- (void)loadingStarted;
|
||||
- (void)loadingDone;
|
||||
- (void)focusURLBar;
|
||||
|
||||
// call to update the image of the lock icon with a value from nsIWebProgressListener
|
||||
|
@ -211,9 +213,9 @@ typedef enum
|
|||
- (IBAction)viewSource:(id)aSender; // focussed frame or page
|
||||
- (IBAction)viewPageSource:(id)aSender; // top-level page
|
||||
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList;
|
||||
- (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
|
||||
url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename;
|
||||
- (void)saveDocument:(BOOL)focusedFrame filterView:(NSView*)aFilterView;
|
||||
- (void)saveURL:(NSView*)aFilterView url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename;
|
||||
|
||||
- (IBAction)printDocument:(id)aSender;
|
||||
- (IBAction)pageSetup:(id)aSender;
|
||||
- (IBAction)performSearch:(id)aSender;
|
||||
|
@ -302,6 +304,7 @@ typedef enum
|
|||
- (IBAction)bookmarkLink: (id)aSender;
|
||||
|
||||
- (IBAction)copyLinkLocation:(id)aSender;
|
||||
- (IBAction)copyImage:(id)sender;
|
||||
- (IBAction)copyImageLocation:(id)sender;
|
||||
|
||||
- (BookmarksToolbar*) bookmarksToolbar;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче