File:  [mozdev] / chimera / ProgressDlgController.mm
Revision 1.10: download - view: text, annotated - select for diffs - revision graph
Mon Feb 4 05:18:41 2002 UTC (17 years, 10 months ago) by macserv
Branches: MAIN
CVS tags: HEAD
Fixing toolbar customization crash.  The toolbar:itemForItemIdentifier:willBeInsertedIntoToolbar: method gets called for three reasons: 1. To draw the toolbar itself.  2. To draw the allowed items in the customization sheet.  3. To draw the default toolbar in the customization sheet.  The crash occurred because, when the method was called to draw items in the customization sheet, the references were reassigned to the items in the sheet.  To fix this, i put an if ( willBeInserted ) around the reference assignment.  When the drawing method is called, willBeInserted will only be YES if the item is actually being drawn in the toolbar.  Thus, the reference is only assigned for actual, inserted toolbar items.  Whew!

    1: //
    2: //  ProgressDlgController.m
    3: //  Chimera
    4: //
    5: //  Created by David Hyatt on Sat Feb 02 2002.
    6: //  Copyright (c) 2001 __MyCompanyName__. All rights reserved.
    7: //
    8: 
    9: #import "ProgressDlgController.h"
   10: 
   11: #include "nsCOMPtr.h"
   12: #include "nsString.h"
   13: #include "nsIWebBrowserPersist.h"
   14: #include "nsIInputStream.h"
   15: #include "nsIURL.h"
   16: #include "nsILocalFile.h"
   17: #include "nsIDOMHTMLDocument.h"
   18: #include "nsIWebProgressListener.h"
   19: #include "nsIComponentManager.h"
   20: #include "nsIPrefBranch.h"
   21: 
   22: const char* prefContractID = "@mozilla.org/preferences-service;1";
   23: 
   24: class nsDownloadListener : public nsIWebProgressListener
   25: {
   26: public:
   27:     nsDownloadListener(ProgressDlgController* aController,
   28:                        nsIWebBrowserPersist* aPersist,
   29:                        nsISupports* aSource,
   30:                        NSString* aDestination,
   31:                        const char* aContentType,
   32:                        nsIInputStream* aPostData,
   33:                        BOOL aBypassCache)
   34:     {
   35:         NS_INIT_REFCNT();
   36:         mController = aController;
   37:         mWebPersist = aPersist;
   38:         // The source is either a simple URL or a complete document.
   39:         mURL = do_QueryInterface(aSource);
   40:         if (!mURL)
   41:             mDocument = do_QueryInterface(aSource);
   42:         nsCAutoString dstStr = [aDestination cString];
   43:         NS_NewLocalFile(dstStr.get(), PR_FALSE, getter_AddRefs(mDestination));
   44:         mContentType = aContentType;
   45:         mPostData = aPostData;
   46:         mBypassCache = aBypassCache;
   47:     };
   48:     
   49:     virtual ~nsDownloadListener() {};
   50: 
   51:     NS_DECL_ISUPPORTS
   52:     NS_DECL_NSIWEBPROGRESSLISTENER
   53:   
   54: public:
   55:     void BeginDownload();
   56:     void InitDialog();
   57:     
   58: private: // Member variables
   59:     ProgressDlgController* mController; // Controller for our UI.
   60:     nsCOMPtr<nsIWebBrowserPersist> mWebPersist; // Our web persist object.
   61:     nsCOMPtr<nsIURL> mURL; // The URL of our source file. Null if we're saving a complete document.
   62:     nsCOMPtr<nsILocalFile> mDestination; // Our destination URL.
   63:     nsCString mContentType; // Our content type string.
   64:     nsCOMPtr<nsIDOMHTMLDocument> mDocument; // A DOM document.  Null if we're only saving a simple URL.
   65:     nsCOMPtr<nsIInputStream> mPostData;  // For complete documents, this is our post data from session history.
   66:     PRBool mBypassCache; // Whether we should bypass the cache or not.
   67: };
   68: 
   69: NS_IMPL_ISUPPORTS1(nsDownloadListener, nsIWebProgressListener)
   70: 
   71: /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
   72: NS_IMETHODIMP 
   73: nsDownloadListener::OnProgressChange(nsIWebProgress *aWebProgress, 
   74: 					 nsIRequest *aRequest, 
   75: 					 PRInt32 aCurSelfProgress, 
   76: 					 PRInt32 aMaxSelfProgress, 
   77: 					 PRInt32 aCurTotalProgress, 
   78: 					 PRInt32 aMaxTotalProgress)
   79: {
   80:   return NS_OK;
   81: }
   82: 
   83: /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
   84: NS_IMETHODIMP 
   85: nsDownloadListener::OnLocationChange(nsIWebProgress *aWebProgress, 
   86: 					 nsIRequest *aRequest, 
   87: 					 nsIURI *location)
   88: {
   89:   return NS_OK;
   90: }
   91: 
   92: /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
   93: NS_IMETHODIMP 
   94: nsDownloadListener::OnStatusChange(nsIWebProgress *aWebProgress, 
   95: 				       nsIRequest *aRequest, 
   96: 				       nsresult aStatus, 
   97: 				       const PRUnichar *aMessage)
   98: {
   99:   return NS_OK;
  100: }
  101: 
  102: /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */
  103: NS_IMETHODIMP 
  104: nsDownloadListener::OnSecurityChange(nsIWebProgress *aWebProgress, 
  105: 					              nsIRequest *aRequest, 
  106:                                   PRInt32 state)
  107: {
  108:   return NS_OK;
  109: }
  110: 
  111: // Implementation of nsIWebProgressListener
  112: /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */
  113: NS_IMETHODIMP 
  114: nsDownloadListener::OnStateChange(nsIWebProgress *aWebProgress, 
  115: 				      nsIRequest *aRequest, 
  116: 				      PRInt32 aStateFlags, 
  117: 				      PRUint32 aStatus)
  118: {
  119:     return NS_OK;
  120: }
  121: 
  122: void
  123: nsDownloadListener::BeginDownload()
  124: {
  125:     if (mWebPersist) {
  126:         mWebPersist->SetProgressListener(this);
  127:         PRInt32 flags = nsIWebBrowserPersist::PERSIST_FLAGS_NO_CONVERSION | 
  128:                         nsIWebBrowserPersist::PERSIST_FLAGS_REPLACE_EXISTING_FILES;
  129:         if (mBypassCache)
  130:             flags |= nsIWebBrowserPersist::PERSIST_FLAGS_BYPASS_CACHE;
  131:         else
  132:             flags |= nsIWebBrowserPersist::PERSIST_FLAGS_FROM_CACHE;
  133:             
  134:         if (mURL)
  135:             mWebPersist->SaveURI(mURL, mPostData, mDestination);
  136:         else {
  137:             PRInt32 encodingFlags = 0;
  138:             nsCOMPtr<nsILocalFile> filesFolder;
  139:             
  140:             if (!mContentType.Equals("text/plain")) {
  141:                 // Create a local directory in the same dir as our file.  It
  142:                 // will hold our associated files.
  143:                 filesFolder = do_CreateInstance("@mozilla.org/file/local;1");
  144:                 nsXPIDLString unicodePath;
  145:                 mDestination->GetUnicodePath(getter_Copies(unicodePath));
  146:                 filesFolder->InitWithUnicodePath(unicodePath.get());
  147:                 
  148:                 nsXPIDLCString leafName;
  149:                 filesFolder->GetLeafName(getter_Copies(leafName));
  150:                 nsCAutoString nameMinusExt(leafName.get());
  151:                 PRInt32 index = nameMinusExt.RFind(".");
  152:                 if (index >= 0)
  153:                     nameMinusExt.Left(nameMinusExt, index);
  154:                 nameMinusExt += " Files"; // XXXdwh needs to be localizable!
  155:                 filesFolder->SetLeafName(nameMinusExt.get());
  156:                 PRBool exists = PR_FALSE;
  157:                 filesFolder->Exists(&exists);
  158:                 if (!exists)
  159:                     filesFolder->Create(nsILocalFile::DIRECTORY_TYPE, 0755);
  160:             }
  161:             else
  162:                 encodingFlags |= nsIWebBrowserPersist::ENCODE_FLAGS_FORMATTED |
  163:                                  nsIWebBrowserPersist::ENCODE_FLAGS_ABSOLUTE_LINKS |
  164:                                  nsIWebBrowserPersist::ENCODE_FLAGS_NOFRAMES_CONTENT;
  165:                                  
  166:             mWebPersist->SaveDocument(mDocument, mDestination, filesFolder, mContentType.get(),
  167:                                       encodingFlags, 80);
  168:         }
  169:     }
  170:     
  171:     InitDialog();
  172: }
  173: 
  174: void
  175: nsDownloadListener::InitDialog()
  176: {
  177:     if (!mURL && !mDocument)
  178:         return;
  179:         
  180:     if (mWebPersist) {
  181:         if (mURL) {
  182:             nsXPIDLCString spec;
  183:             mURL->GetSpec(getter_Copies(spec));
  184:             [mController setSourceURL: spec.get()];
  185:         }
  186:         else {
  187:             nsAutoString spec;
  188:             mDocument->GetURL(spec);
  189:             nsCAutoString spec2; spec2.AssignWithConversion(spec);
  190:             [mController setSourceURL: spec2.get()];
  191:         }
  192:     }
  193:     
  194:     nsXPIDLString path;
  195:     mDestination->GetUnicodePath(getter_Copies(path));
  196:     nsCAutoString pathStr; pathStr.AssignWithConversion(path.get());
  197:     [mController setDestination: pathStr.get()];
  198:     
  199:     
  200: }
  201: 
  202: static NSString *SaveFileToolbarIdentifier			= @"Save File Dialog Toolbar";
  203: static NSString *CancelToolbarItemIdentifier		= @"Cancel Toolbar Item";
  204: static NSString *PauseResumeToolbarItemIdentifier	= @"Pause and Resume Toggle Toolbar Item";
  205: static NSString *ShowFileToolbarItemIdentifier		= @"Show File Toolbar Item";
  206: static NSString *OpenFileToolbarItemIdentifier		= @"Open File Toolbar Item";
  207: static NSString *LeaveOpenToolbarItemIdentifier		= @"Leave Open Toggle Toolbar Item";
  208: 
  209: @interface ProgressDlgController(Private)
  210: -(void)setupToolbar;
  211: @end
  212: 
  213: @implementation ProgressDlgController
  214: 
  215: -(void)setWebPersist:(nsIWebBrowserPersist*)aPersist 
  216:               source:(nsISupports*)aSource
  217:          destination:(NSString*)aDestination
  218:          contentType:(const char*)aContentType
  219:             postData:(nsIInputStream*)aInputStream
  220:          bypassCache:(BOOL)aBypassCache
  221: {
  222:     mDownloadListener = new nsDownloadListener(self, aPersist, aSource,
  223:                                                aDestination, aContentType,
  224:                                                aInputStream, aBypassCache);
  225:     NS_ADDREF(mDownloadListener);
  226: }
  227: 
  228: -(void) setSourceURL: (const char*)aSource
  229: {
  230:     [mFromField setStringValue: [NSString stringWithCString: aSource]];
  231: }
  232: 
  233: -(void) setDestination: (const char*)aDestination
  234: {
  235:     [mToField setStringValue: [NSString stringWithCString: aDestination]];
  236: }
  237: 
  238: - (void)windowDidLoad
  239: {
  240:     mDownloadIsPaused = NO; 
  241:     nsCOMPtr<nsIPrefBranch> prefs(do_GetService(prefContractID));
  242:     PRBool save = PR_FALSE;
  243:     prefs->GetBoolPref("browser.download.progressDnldDialog.keepAlive", 
  244:                         &save);
  245:     mSaveFileDialogShouldStayOpen = save;
  246: 
  247:     [self setupToolbar];
  248:     if (mDownloadListener)
  249:         mDownloadListener->BeginDownload();
  250: }
  251: 
  252: - (void)setupToolbar
  253: {
  254:     NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:SaveFileToolbarIdentifier] autorelease];
  255: 
  256:     [toolbar setDisplayMode:NSToolbarDisplayModeDefault];
  257:     [toolbar setAllowsUserCustomization:YES];
  258:     [toolbar setAutosavesConfiguration:YES];
  259:     [toolbar setDelegate:self];
  260:     [[self window] setToolbar:toolbar];
  261: }
  262: 
  263: - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar
  264: {
  265:     NSLog(@"toolbarAllowedItemIdentifiers:");
  266:     return [NSArray arrayWithObjects: CancelToolbarItemIdentifier,
  267:         PauseResumeToolbarItemIdentifier,
  268:         ShowFileToolbarItemIdentifier,
  269:         OpenFileToolbarItemIdentifier,
  270:         LeaveOpenToolbarItemIdentifier,
  271:         NSToolbarCustomizeToolbarItemIdentifier,
  272:         NSToolbarFlexibleSpaceItemIdentifier,
  273:         NSToolbarSpaceItemIdentifier,
  274:         NSToolbarSeparatorItemIdentifier,
  275:         nil];
  276: }
  277: 
  278: - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar
  279: {
  280:     NSLog(@"toolbarDefaultItemIdentifiers:");
  281:     return [NSArray arrayWithObjects: CancelToolbarItemIdentifier,
  282:         PauseResumeToolbarItemIdentifier,
  283:         NSToolbarFlexibleSpaceItemIdentifier,
  284:         LeaveOpenToolbarItemIdentifier,
  285:         NSToolbarFlexibleSpaceItemIdentifier,
  286:         ShowFileToolbarItemIdentifier,
  287:         OpenFileToolbarItemIdentifier,
  288:         nil];
  289: }
  290: 
  291: - (NSToolbarItem *) toolbar:(NSToolbar *)toolbar
  292:       itemForItemIdentifier:(NSString *)itemIdent
  293:   willBeInsertedIntoToolbar:(BOOL)willBeInserted
  294: {
  295:     NSLog(@"toolbar:itemForItemIdentifier:%@ willBeInsertedIntoToolbar:%d", itemIdent, willBeInserted);
  296:     NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier:itemIdent] autorelease];
  297: 
  298:     if ( [itemIdent isEqual:CancelToolbarItemIdentifier] ) {
  299:         [toolbarItem setLabel:@"Cancel"];
  300:         [toolbarItem setPaletteLabel:@"Cancel Download"];
  301:         [toolbarItem setToolTip:@"Cancel this file download"];
  302:         [toolbarItem setImage:[NSImage imageNamed:@"saveCancel"]];
  303:         [toolbarItem setTarget:self];
  304:         [toolbarItem setAction:@selector(cancel)];
  305:     } else if ( [itemIdent isEqual:PauseResumeToolbarItemIdentifier] ) {
  306:         [toolbarItem setLabel:@"Pause"];
  307:         [toolbarItem setPaletteLabel:@"Pause Download"];
  308:         [toolbarItem setToolTip:@"Pause this FTP file download"];
  309:         [toolbarItem setImage:[NSImage imageNamed:@"savePause"]];
  310:         [toolbarItem setTarget:self];
  311:         [toolbarItem setAction:@selector(pauseAndResumeDownload)];
  312:         if ( willBeInserted ) {
  313:             pauseResumeToggleToolbarItem = toolbarItem; //establish reference
  314:         }
  315:     } else if ( [itemIdent isEqual:ShowFileToolbarItemIdentifier] ) {
  316:         [toolbarItem setLabel:@"Show File"];
  317:         [toolbarItem setPaletteLabel:@"Show File"];
  318:         [toolbarItem setToolTip:@"Show the saved file in the Finder"];
  319:         [toolbarItem setImage:[NSImage imageNamed:@"saveShowFile"]];
  320:         [toolbarItem setTarget:self];
  321:         [toolbarItem setAction:@selector(showFile)];
  322:     } else if ( [itemIdent isEqual:OpenFileToolbarItemIdentifier] ) {
  323:         [toolbarItem setLabel:@"Open File"];
  324:         [toolbarItem setPaletteLabel:@"Open File"];
  325:         [toolbarItem setToolTip:@"Open the saved file in its default application."];
  326:         [toolbarItem setImage:[NSImage imageNamed:@"saveOpenFile"]];
  327:         [toolbarItem setTarget:self];
  328:         [toolbarItem setAction:@selector(openFile)];
  329:     } else if ( [itemIdent isEqual:LeaveOpenToolbarItemIdentifier] ) {
  330:         if ( mSaveFileDialogShouldStayOpen ) {
  331:             [toolbarItem setLabel:@"Leave Open"];
  332:             [toolbarItem setPaletteLabel:@"Toggle Close Behavior"];
  333:             [toolbarItem setToolTip:@"Window will stay open when download finishes."];
  334:             [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]];
  335:             [toolbarItem setTarget:self];
  336:             [toolbarItem setAction:@selector(toggleLeaveOpen)];
  337:         } else {
  338:             [toolbarItem setLabel:@"Close When Done"];
  339:             [toolbarItem setPaletteLabel:@"Toggle Close Behavior"];
  340:             [toolbarItem setToolTip:@"Window will close automatically when download finishes."];
  341:             [toolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]];
  342:             [toolbarItem setTarget:self];
  343:             [toolbarItem setAction:@selector(toggleLeaveOpen)];
  344:         }
  345:         if ( willBeInserted ) {
  346:             leaveOpenToggleToolbarItem = toolbarItem; //establish reference
  347:         }
  348:     } else {
  349:         toolbarItem = nil;
  350:     }
  351: 
  352:     return toolbarItem;
  353: }
  354: 
  355: -(void)cancel
  356: {
  357:     NSLog(@"Request to cancel download.");
  358:     //Put logic here!
  359: }
  360: 
  361: -(void)pauseAndResumeDownload
  362: {
  363:     if ( ! mDownloadIsPaused ) {
  364:         //Do logic to pause download
  365:         mDownloadIsPaused = YES;
  366:         [pauseResumeToggleToolbarItem setLabel:@"Resume"];
  367:         [pauseResumeToggleToolbarItem setPaletteLabel:@"Resume Download"];
  368:         [pauseResumeToggleToolbarItem setToolTip:@"Resume the paused FTP download"];
  369:         [pauseResumeToggleToolbarItem setImage:[NSImage imageNamed:@"saveResume"]];
  370:     } else {
  371:         //Do logic to resume download
  372:         mDownloadIsPaused = NO;
  373:         [pauseResumeToggleToolbarItem setLabel:@"Pause"];
  374:         [pauseResumeToggleToolbarItem setPaletteLabel:@"Pause Download"];
  375:         [pauseResumeToggleToolbarItem setToolTip:@"Pause this FTP file download"];
  376:         [pauseResumeToggleToolbarItem setImage:[NSImage imageNamed:@"savePause"]];
  377:     }
  378: }
  379: 
  380: -(void)showFile
  381: {
  382:     NSLog(@"Request to show file.");
  383: }
  384: 
  385: -(void)openFile
  386: {
  387:     NSLog(@"Request to open file.");
  388: }
  389: 
  390: -(void)toggleLeaveOpen
  391: {
  392:     if ( ! mSaveFileDialogShouldStayOpen ) {
  393:         mSaveFileDialogShouldStayOpen = YES;
  394:         [leaveOpenToggleToolbarItem setLabel:@"Leave Open"];
  395:         [leaveOpenToggleToolbarItem setPaletteLabel:@"Toggle Close Behavior"];
  396:         [leaveOpenToggleToolbarItem setToolTip:@"Window will stay open when download finishes."];
  397:         [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenYES"]];
  398:     } else {
  399:         mSaveFileDialogShouldStayOpen = NO;
  400:         [leaveOpenToggleToolbarItem setLabel:@"Close When Done"];
  401:         [leaveOpenToggleToolbarItem setPaletteLabel:@"Toggle Close Behavior"];
  402:         [leaveOpenToggleToolbarItem setToolTip:@"Window will close automatically when download finishes."];
  403:         [leaveOpenToggleToolbarItem setImage:[NSImage imageNamed:@"saveLeaveOpenNO"]];
  404:     }
  405:     
  406:     nsCOMPtr<nsIPrefBranch> prefs(do_GetService(prefContractID));
  407:     prefs->SetBoolPref("browser.download.progressDnldDialog.keepAlive", mSaveFileDialogShouldStayOpen);
  408: }
  409: 
  410: - (void)windowWillClose:(NSNotification *)notification
  411: {
  412:     [self autorelease];
  413: }
  414: 
  415: - (void)dealloc
  416: {
  417:     NS_IF_RELEASE(mDownloadListener);
  418:     [super dealloc];
  419: }
  420: 
  421: @end

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>